package nc.api.arap.resource;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Logger;
import nc.bs.trade.business.HYPubBO;
import nc.bs.trade.business.HYSuperDMO;
import nc.itf.bd.defdoc.IDefdocService;
import nc.itf.pmpub.project.pub.IProjectServiceForPu;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapProcessor;
import nc.vo.arap.basebill.BaseAggVO;
import nc.vo.arap.gathering.AggGatheringBillVO;
import nc.vo.arap.gathering.GatheringBillItemVO;
import nc.vo.arap.gathering.GatheringBillVO;
import nc.vo.bd.bankaccount.BankAccbasVO;
import nc.vo.bd.defdoc.DefdocVO;
import nc.vo.pmpub.project.ProjectHeadVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.CircularlyAccessibleValueObject;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.pattern.pub.MathTool;
import nc.vo.so.m30.entity.SaleOrderBVO;
import nc.vo.so.m30.entity.SaleOrderHVO;
import nccloud.api.rest.utils.NCCRestUtils;
import nccloud.api.rest.utils.ResultMessageUtil;
import nccloud.commons.lang.StringUtils;
import nccloud.pubitf.arap.openapi.IGatheringbillOpenService;
import org.json.JSONString;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.GZIPInputStream;

@Path("arap/gatheringbill")
public class GatheringbillRestResource extends ArapBaseRestResource {

    HYSuperDMO dmo = null;

    public HYSuperDMO getSuperDMO() {
        if (dmo == null) {
            dmo = new HYSuperDMO();
        }
        return dmo;
    }

    /**
     * 该收款单保存为BIP专业保存方法。请谨慎修改；
     *
     * @param str
     * @return
     */

    @POST
    @Path("/bipinsert")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public JSONString bipInsertPaybill(JSONString str) {
        InvocationInfoProxy.getInstance().setGroupId("0001A110000000000677");
        NCCRestUtils.initInvocationInfo();
        String json = str.toJSONString();
        Map<String, Object> billMap = (Map) fromJson(json, Map.class);
        billMap.put("recaccount", billMap.get("ar_recaccount"));// 收款银行账户
        GatheringBillVO headvo = (GatheringBillVO) fromJsonToVO(billMap, GatheringBillVO.class);
        // 根据收款银行账户带出银行类别
        String def5 = getBankTypeByAccount(headvo.getRecaccount());
        headvo.setDef5(def5); // 银行类别
        headvo.setDef28(headvo.getBilldate().toStdString());// 交易日期
        // 汇率为空时，默认为1
        if (headvo.getRate() == null) {
            headvo.setRate(UFDouble.ONE_DBL);
        }
        // 结算方式名称
        Object balatypeName = "";
        // 金额
        UFDouble money = new UFDouble(0);
        // 税率
        UFDouble ntaxrate = new UFDouble(0);
        // 税码
        String ctaxcode = "";
        BaseDAO dao = new BaseDAO();
        // 销售订单号 从表体拿
        String csaleorderid = "";
        List<Map<String, Object>> itemMaps = (List) billMap.get("items");
        List<GatheringBillItemVO> itemvos = new ArrayList<GatheringBillItemVO>();
        if (itemMaps != null && itemMaps.size() > 0) {
            for (Map<String, Object> item : itemMaps) {
                GatheringBillItemVO itemvo = (GatheringBillItemVO) fromJsonToVO(item, GatheringBillItemVO.class);
                csaleorderid = itemvo.getDef37();
            }
        }
        try {
            HYPubBO hybo = new HYPubBO();
            headvo.setIsinit(new UFBoolean(false));
            // 默认 收款类型 默认合同收款单
            Object pk_billtypecode = hybo.findColValue("bd_billtype", "PK_BILLTYPECODE", "billtypename = '合同收款单' ");
            headvo.setPk_tradetype(pk_billtypecode.toString());
            // 业务流程 默认【收款传结算】
            Object pk_busitype = hybo.findColValue("bd_busitype", "busicode", "businame = '收款传结算' ");
            headvo.setPk_busitype(pk_busitype.toString());
            // 往来对象0-客户 2-部门 3-业务员 默认客户
            headvo.setObjtype(0);
            // 销售订单号
            if (StringUtils.isEmpty(csaleorderid)) {
                throw new BusinessException("销售订单不能为空");
                // return ResultMessageUtil.exceptionToJSON("销售订单不能为空",
                // APIErrCodeEnum.BUSINESSEXCCODE.getCode());
            }
            // 客户
            Object customerid = hybo.findColValue("so_saleorder", "ccustomerid",
                    "csaleorderid = '" + csaleorderid + "' ");
            Object customerCode = hybo.findColValue("bd_customer", "code", "pk_customer = '" + customerid + "' ");
            if (customerid == null || customerCode == null) {
                throw new BusinessException("销售订单的关联客户不能为空");
            }
            headvo.setCustomer(customerCode.toString());

            Object tr = dao.executeQuery(
                    "select ntaxrate from  so_saleorder_b where csaleorderid = '" + csaleorderid + "'",
                    new ColumnProcessor());
            // ntaxrate = new UFDouble(tr.toString());
            // 税码
            Object ctaxcodeid = hybo.findColValue("so_saleorder_b", "ctaxcodeid",
                    "csaleorderid = '" + csaleorderid + "' ");
            Object tc = hybo.findColValue("bd_taxcode", "code", "pk_taxcode = '" + ctaxcodeid + "' ");
            ctaxcode = getString_TrimAsNull(tc);
            // 业务员
            Object cemployeeid = hybo.findColValue("so_saleorder", "cemployeeid",
                    "csaleorderid = '" + csaleorderid + "' ");
            if (cemployeeid != null) {// 能够获取到值，但是该值可能在销售订单生成的时候，没有翻译，依然存的是人员编码，如果存的是人员编码，则说明该人员在erp系统中不存在
                Object cemployeeCode = hybo.findColValue("bd_psndoc", "code", "pk_psndoc = '" + cemployeeid + "' ");
                if (cemployeeCode != null) {
                    headvo.setPk_psndoc(cemployeeCode.toString());
                    // 部门
                    Object deptCode = hybo.findColValue("org_orgs", "code",
                            " pk_org in( select pk_dept from bd_psnjob where pk_psndoc = '" + cemployeeid + "')");
                    if (deptCode != null) {
                        headvo.setPk_deptid(deptCode.toString());
                    }
                }
            }
            // pk_currtype 币种编码 默认人民币
            if (headvo.getPk_currtype() == null || headvo.getPk_currtype().isEmpty()) {
                headvo.setPk_currtype("CNY");
            }

            // accessorynum 附件张数 默认2
            headvo.setAccessorynum(2);
            // 制单人 默认BIP
            headvo.setBillmaker("BIP");
            // 结算方式名称
            String balatypeCode = headvo.getPk_balatype();
            if (!StringUtils.isEmpty(balatypeCode)) {
                Object pk_balatype = hybo.findColValue("bd_balatype", "pk_balatype", " code = '" + balatypeCode + "' ");
//			          headvo.setPk_balatype(pk_balatype.toString());
                if (pk_balatype != null) {
                    balatypeName = hybo.findColValue("bd_balatype", "name", " code = '" + balatypeCode + "' ");
                }

            }

            // 银行收款账号
            // 原币金额
            // 单据状态
            headvo.setBillstatus(-1);
            // 单据来源系统编码
            headvo.setSrc_syscode(17);
            // 合同金额
            // 结算组织
            headvo.setSett_org(headvo.getPk_org());
        } catch (Exception e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }

        if (itemMaps != null && itemMaps.size() > 0) {
            for (Map<String, Object> item : itemMaps) {
                GatheringBillItemVO itemvo = (GatheringBillItemVO) fromJsonToVO(item, GatheringBillItemVO.class);

                try {
                    HYPubBO hybo = new HYPubBO();
                    itemvo.setRecaccount(headvo.getRecaccount());
                    // pk_balatype 结算方式 表头带出
                    itemvo.setPk_balatype(headvo.getPk_balatype());
                    // 票据类型 checktype 结算方式：银行承兑汇票-电子、银行承兑汇票-纸质=银行承兑汇票；商业承兑汇票-电子、商业承兑汇票-纸质=商业承兑汇票
                    String checktypeName = "";
                    if ("银行承兑汇票-电子".equals(balatypeName)) {
                        checktypeName = "电子银行承兑汇票";
                    } else if ("商业承兑汇票-电子".equals(balatypeName)) {
                        checktypeName = "电子商业承兑汇票";
                    } else if ("商业承兑汇票-纸质".equals(balatypeName)) {
                        checktypeName = "商业承兑汇票";
                    } else if ("银行承兑汇票-纸质".equals(balatypeName)) {
                        checktypeName = "银行承兑汇票";
                    }

                    if (checktypeName != "") {
                        Object checktypeCode = hybo.findColValue("bd_notetype", "code",
                                " name = '" + checktypeName + "' ");
                        itemvo.setChecktype(checktypeCode.toString());
                    }

                    // objtype 往来对象0-客户 2-部门 3-业务员 表头带出
                    itemvo.setObjtype(headvo.getObjtype());
                    // supplier 客户编码 表头带出
                    itemvo.setCustomer(headvo.getCustomer());
                    // pk_dept 部门编码 表头带出
                    itemvo.setPk_deptid(headvo.getPk_deptid());
                    // pk_psndoc 业务员编码 表头带出
                    itemvo.setPk_psndoc(headvo.getPk_psndoc());
                    // pk_currtype 币种编码 表头带出
                    itemvo.setPk_currtype(headvo.getPk_currtype());
                    // prepay 收款性质 默认应收款 0
                    itemvo.setPrepay(0);
                    //
                    UFDouble money_cr = itemvo.getMoney_cr();
                    UFDouble local_tax_cr = money_cr.multiply(ntaxrate).div(100);
                    itemvo.setLocal_tax_cr(local_tax_cr);
                    //
                    UFDouble notax_cr = money_cr.sub(local_tax_cr);
                    itemvo.setNotax_cr(notax_cr);
                    // zhangxinah增加组织本币无税金额(贷方)
                    itemvo.setLocal_notax_cr(notax_cr);
                    // 汇率为空时，默认为1
                    if (headvo.getRate() == null) {
                        itemvo.setRate(UFDouble.ONE_DBL);
                    } else {
                        itemvo.setRate(headvo.getRate());
                    }
                    //
                    itemvo.setTaxcodeid(ctaxcode);
                    //
                    itemvo.setTaxrate(ntaxrate);
                    // 收支项目
                    itemvo.setPk_subjcode("201");
                    money = money.add(itemvo.getMoney_cr());
                    itemvo.setLocal_money_cr(
                            itemvo.getMoney_cr().multiply(itemvo.getRate()).setScale(2, UFDouble.ROUND_HALF_UP));
                    Object def2 = itemvo.getDef2();
                    if (def2 != null)
                        itemvo.setDef2(hybo.findColValue("bd_defdoc", "pk_defdoc", " code = '" + def2 + "' ") + "");
                    Object def3 = itemvo.getDef3();
                    if (def3 != null)
                        itemvo.setDef3(hybo.findColValue("bd_defdoc", "pk_defdoc", " code = '" + def3 + "' ") + "");
                    Object def6 = itemvo.getDef6();
                    if (def6 != null)
                        itemvo.setDef6(hybo.findColValue("bd_defdoc", "pk_defdoc", " code = '" + def6 + "' ") + "");
                    Object def36 = itemvo.getDef36();
                    if (def36 != null)
                        itemvo.setDef36(hybo.findColValue("bd_defdoc", "pk_defdoc", " code = '" + def36 + "' ") + "");

                    HYSuperDMO dmo = new HYSuperDMO();
                    SaleOrderHVO[] hvo = (SaleOrderHVO[]) dmo.queryByWhereClause(SaleOrderHVO.class,
                            "vbillcode='" + def2 + "' and dr=0");
                    if (hvo == null || hvo.length == 0) {
                        throw new BusinessException("该销售订单在ERP中被删除，订单号：" + def2);
                    }
                    SaleOrderBVO[] bvos = (SaleOrderBVO[]) dmo.queryByWhereClause(SaleOrderBVO.class,
                            "csaleorderid='" + hvo[0].getPrimaryKey() + "'");
                    if (bvos != null) {
                        itemvo.setSrc_billid(bvos[0].getCsaleorderid());
                        itemvo.setSrc_itemid(bvos[0].getCsaleorderbid());
                        itemvo.setSrc_billtype("30");
                        itemvo.setSrc_tradetype(hvo[0].getVtrantypecode());
                        itemvo.setTop_billid(bvos[0].getCsaleorderid());
                        itemvo.setTop_itemid(bvos[0].getCsaleorderbid());
                        itemvo.setTop_billtype("30");
                    }

                } catch (Exception e) {
                    return ResultMessageUtil.exceptionToJSON(e);
                }

                itemvos.add(itemvo);
            }
        }

        headvo.setMoney(money);
        headvo.setGloballocal(money);
        // headvo.setRate(new UFDouble(1));
        headvo.setLocal_money(money.multiply(headvo.getRate()).setScale(2, UFDouble.ROUND_HALF_UP));
        AggGatheringBillVO bill = new AggGatheringBillVO();
        bill.setParentVO(headvo);
        bill.setChildrenVO((CircularlyAccessibleValueObject[]) itemvos.toArray(new GatheringBillItemVO[0]));
        try {
            Map<String, String> returnMap = ((IGatheringbillOpenService) NCLocator.getInstance()
                    .lookup(IGatheringbillOpenService.class)).saveBill(bill);
            JSONString resultJson = ResultMessageUtil.toJSON(returnMap);
            // 保存后动作
            JSONObject js_result = JSON.parseObject(resultJson.toJSONString());
            if (js_result.containsKey("success")) {
                if (js_result.getString("success").equals("true")) {
                    if (js_result.containsKey("data")) {
                        JSONObject js_data = js_result.getJSONObject("data");
                        String pk_gatherid = js_data.getString("pk_bill");
                        String pk_org = js_data.getString("pk_org");
                        GatheringBillItemVO[] billItemVOs = (GatheringBillItemVO[]) bill.getChildrenVO();
                        for (GatheringBillItemVO gatheringBillItemVO : billItemVOs) {
                            afterChangeMny(gatheringBillItemVO.getSrc_billid(), pk_org, billItemVOs[0].getDef6(),
                                    pk_gatherid);
                        }
                    }
                }
            }
            return resultJson;
        } catch (BusinessException e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
    }

    // 实际收款金额 01无约定预付款 02有约定已收到预付款 03有约定未收到款

    /**
     * @param csaleorderid 销售订单id
     * @param pk_org       组织
     * @param ctid         合同id
     * @param pk_gatherid  收款单id
     */
    private void afterChangeMny(String csaleorderid, String pk_org, String ctid, String pk_gatherid) {
        try {
            // 合同id
            if (StringUtils.isEmpty(ctid)) {
                return;
            }
            // 获取销售订单表头
            SaleOrderHVO hvo = (SaleOrderHVO) getSuperDMO().queryByPrimaryKey(SaleOrderHVO.class, csaleorderid);
            if (hvo == null) {
                return;
            }
            String vdef9 = hvo.getVdef9();// BIP 合同销售订单id
            if (StringUtils.isEmpty(vdef9)) {// 为空，不是从bip 生成的
                return;
            }
            // 合同金额vdef17
            UFDouble ctmny = new UFDouble(hvo.getVdef17() == null ? "0" : hvo.getVdef17());
            // 预收比例vdef15
            UFDouble yfrate = new UFDouble(hvo.getVdef15() == null ? "0" : hvo.getVdef15());
            UFDouble temp_yf_mny = ctmny.multiply(yfrate);
            // 发货比例vdef16
            UFDouble fhrate = new UFDouble(hvo.getVdef16() == null ? "0" : hvo.getVdef16());
            UFDouble temp_fh_mny = ctmny.multiply(fhrate);
            // vdef14 预付款标识
            String vdef14 = "01";// 01无约定预付款
            // vdef11 发货款标识
            String vdef11 = "fhk03";// fhk03无约定发货款
            UFDouble total_mny = UFDouble.ZERO_DBL;// 当前组织下本合同所有收款单金额累计
            String sum_sql = "select sum(money_cr) as money_cr from ar_gatheritem where def6 not in ('~') and dr=0   and def6='"
                    + ctid + "'";
            Map map = (Map) new BaseDAO().executeQuery(sum_sql, new MapProcessor());
            if (map != null) {
                total_mny = new UFDouble(String.valueOf(map.get("money_cr")));
            }
            if ((MathTool.compareTo(yfrate, UFDouble.ZERO_DBL) == 0)) {

            } else {
                if (MathTool.compareTo(total_mny, temp_yf_mny) >= 0) {// 累计收款金额≥合同金额*预收比例
                    vdef14 = "02"; // 02有约定已收到预付款
                } else {
                    vdef14 = "03";// 03 有约定未收到款
                }
            }
            if ((MathTool.compareTo(fhrate, UFDouble.ZERO_DBL) == 0)) {

            } else {
                if (MathTool.compareTo(total_mny, temp_fh_mny) >= 0) {// 累计收款金额≥合同金额*发货比例
                    vdef11 = "fhk01";// fhk01有约定已收到发货款
                } else {
                    vdef11 = "fhk02";// fhk02有约定未收到发货款
                }
            }
            DefdocVO[] defdocVOs = (DefdocVO[]) getSuperDMO().queryByWhereClause(DefdocVO.class,
                    " pk_defdoclist in (select pk_defdoclist from bd_defdoclist where code='xsdd' ) and code='" + vdef14
                            + "' and dr=0 ");
            if (defdocVOs != null && defdocVOs.length > 0) {
                hvo.setVdef14(defdocVOs[0].getPrimaryKey());
            }

            defdocVOs = (DefdocVO[]) getSuperDMO().queryByWhereClause(DefdocVO.class,
                    " pk_defdoclist in (select pk_defdoclist from bd_defdoclist where code='FHK' ) and code='" + vdef11
                            + "' and dr=0 ");
            if (defdocVOs != null && defdocVOs.length > 0) {
                hvo.setVdef11(defdocVOs[0].getPrimaryKey());
            }
            pushBipCtOrderUpdate(hvo, vdef14, vdef11);
        } catch (DAOException e) {
            e.printStackTrace();
        }
    }

    /**
     * BIP 合同销售订单更新
     *
     * @param hvo
     * @param vdef14 预付款标识
     * @param vdef11 发货款标识
     */
    private void pushBipCtOrderUpdate(SaleOrderHVO hvo, String vdef14, String vdef11) {
        String baseUrl = "";
        Map<String, String> bipParamMap = checkBipParam();
        if (bipParamMap.isEmpty()) {
            return;
        }
        baseUrl = bipParamMap.get("baseUrl");
        String contractSaleOrderUrl = bipParamMap.get("contractSaleOrder");// 开票申请单回传
        if (StringUtils.isEmpty(contractSaleOrderUrl)) {
            return;
        }
        Gson gson = new Gson();
        try {
            String accessToken = getAccessToken(baseUrl, bipParamMap);
            if (accessToken != "") {
                Map<String, String> tokenParam = new HashMap<>();
                tokenParam.put("access_token", accessToken);
                Map<String, String> headers = new HashMap<String, String>();
                headers.put("Content-Type", "application/json");
                String custUpdateUrl = baseUrl + contractSaleOrderUrl;
                JSONObject js_apct_detail = new JSONObject();
                JSONObject js_apct = new JSONObject();
                js_apct.put("id", hvo.getVdef9());
                js_apct.put("isShipRecdAmt", vdef11);
                js_apct.put("isPreRecv", vdef14);
                js_apct.put("actRecvAmt", hvo.getNreceivedmny().floatValue());
                js_apct.put("actPreRecvAmt", hvo.getNpreceivemny().floatValue());
                js_apct_detail.put("HTXSDD", js_apct);
                String resultString = doSendHttp(custUpdateUrl, "POST", tokenParam, "", headers,
                        js_apct_detail.toJSONString());
                Map updateMap = gson.fromJson(resultString, Map.class);
                if (StringUtils.equals("200", updateMap.get("code").toString())) {// 保存更新成功后需要更新日志表
                    getSuperDMO().update(hvo);
                } else {
                }

            }
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DAOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 检查bip参数是否完整
     *
     * @return
     */
    private Map<String, String> checkBipParam() {
        Map<String, String> map = new HashMap<String, String>();
        String strWhere = " pk_defdoclist in (select pk_defdoclist from bd_defdoclist where code='BIP-sq' and dr=0 )  and dr=0";
        try {
            DefdocVO[] defdocVOs = (DefdocVO[]) getSuperDMO().queryByWhereClause(DefdocVO.class, strWhere);
            if (defdocVOs != null && defdocVOs.length > 0) {
                for (DefdocVO defdocVO : defdocVOs) {
                    map.put(defdocVO.getCode().trim(), defdocVO.getName());
                }
            }
        } catch (DAOException e) {
            e.printStackTrace();
        }
        return map;
    }

    private static String doGet(String path, Map<String, String> params) throws IOException {
        HttpURLConnection conn = null;
        InputStream is = null;
        BufferedReader br = null;
        StringBuilder result = new StringBuilder();
        try {
            if (params != null) {
                String paramStr = "";
                for (String key : params.keySet()) {
                    if (!paramStr.isEmpty()) {
                        paramStr += '&';
                    }
                    paramStr += key + '=' + params.get(key);
                }

                if (path.indexOf('?') > 0) {
                    path += '&' + paramStr;
                } else {
                    path += '?' + paramStr;
                }
            }
            // 创建远程url连接对象
            URL url = new URL(path);
            if ("https".equalsIgnoreCase(url.getProtocol())) {// 判定网址是否信任，不信任则调用忽略信任工具类SslUtil
                IgnoreSslUtil.ignoreSsl();
            }
            // 通过远程url连接对象打开一个连接，强转成HTTPURLConnection类
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            // 设置连接超时时间和读取超时时间
            conn.setConnectTimeout(120000);
            conn.setReadTimeout(120000);
            conn.setRequestProperty("Accept", "application/json");
            // 发送请求
            conn.connect();
            // 通过conn取得输入流，并使用Reader读取
            if (200 == conn.getResponseCode()) {
                is = conn.getInputStream();
                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                String line;
                while ((line = br.readLine()) != null) {
                    result.append(line);
                    System.out.println(line);
                }
            } else {
                System.out.println("ResponseCode is an error code:" + conn.getResponseCode());
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result.toString();
    }

    private String getAccessToken(String baseUrl, Map<String, String> bipParamMap)
            throws NoSuchAlgorithmException, InvalidKeyException, IOException {
        String tokenUrl = baseUrl + "/iuap-api-auth/open-auth/selfAppAuth/getAccessToken";
//				String appKey = "f10c4bf17b1d4e1fb08eb82bf8540eab";
        String appKey = bipParamMap.get("appKey");

//				String appSecret = "71dc2a58ca378c1a1143231a62e73e75a60e9236";
        String appSecret = bipParamMap.get("appSecret");
        String accessToken = "";
        Map<String, String> params = new HashMap<>();

        params.put("appKey", appKey);
        String timestamp = String.valueOf(System.currentTimeMillis());
        params.put("timestamp", timestamp);
        // 计算签名
        Map<String, String> treeMap;
        if (params instanceof TreeMap) {
            treeMap = params;
        } else {
            treeMap = new TreeMap<>(params);
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : treeMap.entrySet()) {
            stringBuilder.append(entry.getKey()).append(entry.getValue());
        }
        Mac mac = Mac.getInstance("HmacSHA256");

        mac.init(new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
        String base64String = Base64.getEncoder().encodeToString(signData);
        String signature = URLEncoder.encode(base64String, "UTF-8");
        params.put("signature", signature);

        String responseString = doGet(tokenUrl, params);

        Gson gson = new Gson();
        Map result = gson.fromJson(responseString, Map.class);
        if (StringUtils.equals("00000", result.get("code").toString())) {
            Map<String, Object> tokenInfo = (Map<String, Object>) result.get("data");
            accessToken = (String) tokenInfo.get("access_token");

        }

        return accessToken;
    }

    public static String doSendHttp(String baseUrl, String method, Map<String, String> paramMap, String mediaType,
                                    Map<String, String> headers, String json) {
        HttpURLConnection urlConnection = null;
        InputStream in = null;
        OutputStream out = null;
        BufferedReader bufferedReader = null;
        String result = null;
        try {
            StringBuffer sb = new StringBuffer();
            sb.append(baseUrl);
            if (paramMap != null) {
                sb.append("?");
                for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    sb.append(key + "=" + value).append("&");
                    baseUrl = sb.toString().substring(0, sb.toString().length() - 1);
                }
            }
            URL urlobj = new URL(baseUrl);
            if ("https".equalsIgnoreCase(urlobj.getProtocol())) {// 判定网址是否信任，不信任则调用忽略信任工具类SslUtil
                IgnoreSslUtil.ignoreSsl();
            }
            urlConnection = (HttpURLConnection) urlobj.openConnection();
            urlConnection.setConnectTimeout(50000);
            urlConnection.setRequestMethod(method);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            // 如果设置了自定义头，则打印它们
            if (headers != null && !headers.isEmpty()) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    urlConnection.addRequestProperty(entry.getKey(), entry.getValue());
                }
            }
            if (json != null && json.length() > 0) {
                urlConnection.setDoInput(true);
                urlConnection.setDoOutput(true);
                out = urlConnection.getOutputStream();
                out.write(json.getBytes("utf-8"));
                out.flush();
            }
            int resCode = urlConnection.getResponseCode();
            String ecod = urlConnection.getContentEncoding();
            if (resCode == HttpURLConnection.HTTP_OK || resCode == HttpURLConnection.HTTP_CREATED
                    || resCode == HttpURLConnection.HTTP_ACCEPTED) {
                if (StringUtils.isNotEmpty(ecod) && ecod.equals("gzip")) {
                    in = new GZIPInputStream(urlConnection.getInputStream());
                } else {
                    in = urlConnection.getInputStream();
                }
            } else {
                in = urlConnection.getErrorStream();
            }
            bufferedReader = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuffer temp = new StringBuffer();
            String line = bufferedReader.readLine();
            while (line != null) {
                temp.append(line).append("\r\n");
                line = bufferedReader.readLine();
            }
            if (ecod == null || ecod.equals("gzip")) {
                ecod = Charset.forName("utf-8").name();
            }
            result = new String(temp.toString().getBytes("utf-8"), ecod);
        } catch (Exception e) {
            JSONObject js = new JSONObject();
            js.put("", -1);
            js.put("message", "调用外系统接口失败：" + e.getMessage());
            result = js.toString();
            e.printStackTrace();
        } finally {
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            urlConnection.disconnect();
        }
        return result;
    }

    @POST
    @Path("/insert")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public JSONString insertBill(JSONString str) {
        return insertBill(str, false);
    }

    @POST
    @Path("/insertandcommit")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public JSONString insertAndCommitBill(JSONString str) {
        return insertBill(str, true);
    }

    private JSONString insertBill(JSONString str, boolean isInsertAndCommit) {
        NCCRestUtils.initInvocationInfo();
        String json = str.toJSONString();
        try {
            BaseAggVO bill = fromJsonToAggVO(json, "F2");
            if (isInsertAndCommit) {
                Map<String, Object> returnMap = ((IGatheringbillOpenService) NCLocator.getInstance()
                        .lookup(IGatheringbillOpenService.class)).saveAndCommitBill(bill);
                return ResultMessageUtil.toJSON(returnMap);
            }
            Map<String, String> returnMap = ((IGatheringbillOpenService) NCLocator.getInstance()
                    .lookup(IGatheringbillOpenService.class)).saveBill(bill);
            return ResultMessageUtil.toJSON(returnMap);
        } catch (Exception e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
    }

    @POST
    @Path("/uncommitanddelete")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public JSONString unCommitAndDelBill(JSONString str) {
        try {
            return unCommitAndDelBill(str, "pk_gatherbill", "F2");
        } catch (BusinessException e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
    }

    @POST
    @Path("/query")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public JSONString queryBill(JSONString str) {
        return queryBill(str, "F2");
    }

    @POST
    @Path("/update")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public JSONString updateBill(JSONString str) {
        return updateBill(str, "F2");
    }

    @POST
    @Path("/delete")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public JSONString deleteBill(JSONString str) {
        try {
            return deleteBill(str, "pk_gatherbill", "F2");
        } catch (BusinessException e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
    }

    @POST
    @Path("/commit")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public JSONString commitBill(JSONString str) {
        try {
            return commitBill(str, "pk_gatherbill", "F2");
        } catch (BusinessException e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
    }

    @POST
    @Path("/uncommit")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public JSONString unCommitBill(JSONString str) {
        try {
            return unCommitBill(str, "pk_gatherbill", "F2");
        } catch (BusinessException e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
    }

    public static String getString_TrimAsNull(Object value) {
        if ((value == null) || (value.toString().trim().length() == 0)) {
            return "";
        }
        return value.toString().trim();
    }


    /**
     * 期初合同销售订单认领直接生成高级版收款单
     *
     * @param str
     * @return
     */

    @POST
    @Path("/bipinsert1")
    @Consumes({"application/json"})
    @Produces({"application/json"})
    public JSONString bipInsertPaybill1(JSONString str) throws BusinessException {
        InvocationInfoProxy.getInstance().setGroupId("0001A110000000000677");
        NCCRestUtils.initInvocationInfo();
        String json = str.toJSONString();
        Map<String, Object> billMap = (Map) fromJson(json, Map.class);
        billMap.put("recaccount", billMap.get("ar_recaccount"));
        GatheringBillVO headvo = (GatheringBillVO) fromJsonToVO(billMap, GatheringBillVO.class);
        // 根据收款银行账户带出银行类别
        String def5 = getBankTypeByAccount(headvo.getRecaccount());
        headvo.setDef5(def5); // 银行类别
        headvo.setDef28(headvo.getBilldate().toStdString());// 交易日期
        // 汇率为空时，默认为1
        if (headvo.getRate() == null) {
            headvo.setRate(UFDouble.ONE_DBL);
        }

        // 结算方式名称
        Object balatypeName = "";
        // 金额
        UFDouble money = new UFDouble(0);
        // 税率
        UFDouble ntaxrate = new UFDouble(0);
        // 税码
        String ctaxcode = "";
        BaseDAO dao = new BaseDAO();
        // 销售订单号 从表体拿
//		String csaleorderid = "";

        // 客户 从表体拿
        String customer = "";
        List<Map<String, Object>> itemMaps = (List) billMap.get("items");
        List<GatheringBillItemVO> itemvos = new ArrayList<GatheringBillItemVO>();
        if (itemMaps != null && itemMaps.size() > 0) {
//			for (Map<String, Object> item : itemMaps) {
//				GatheringBillItemVO itemvo = (GatheringBillItemVO) fromJsonToVO(item, GatheringBillItemVO.class);
//				customer = itemvo.getCustomer();
//			}
        }

        try {
            HYPubBO hybo = new HYPubBO();
//			SELECT 	pk_adminorg FROM org_adminorg WHERE code='C042'

            String org = hybo.findColValue("org_adminorg", "pk_adminorg", " code = '" + headvo.getPk_org() + "' ") + "";

            headvo.setIsinit(new UFBoolean(false));
            // 默认 收款类型 默认合同收款单
            Object pk_billtypecode = hybo.findColValue("bd_billtype", "PK_BILLTYPECODE", "billtypename = '合同收款单' ");
            headvo.setPk_tradetype(pk_billtypecode.toString());
            // 业务流程 默认【收款传结算】
            Object pk_busitype = hybo.findColValue("bd_busitype", "busicode", "businame = '收款传结算' ");
            headvo.setPk_busitype(pk_busitype.toString());
            // 往来对象0-客户 2-部门 3-业务员 默认客户
            headvo.setObjtype(0);
//			headvo.setCustomer(customer);

            // pk_currtype 币种编码 默认人民币
            if (headvo.getPk_currtype() == null || headvo.getPk_currtype().isEmpty()) {
                headvo.setPk_currtype("CNY");
            }

            // accessorynum 附件张数 默认2
            headvo.setAccessorynum(2);
            // 制单人 默认BIP
            headvo.setBillmaker("BIP");
            // 结算方式名称
            String balatypeCode = headvo.getPk_balatype();
            if (!StringUtils.isEmpty(balatypeCode)) {
                Object pk_balatype = hybo.findColValue("bd_balatype", "pk_balatype", " code = '" + balatypeCode + "' ");
//			          headvo.setPk_balatype(pk_balatype.toString());
                if (pk_balatype != null) {
                    balatypeName = hybo.findColValue("bd_balatype", "name", " code = '" + balatypeCode + "' ");
                }

            }

            // 银行收款账号
            // 原币金额
            // 单据状态
            headvo.setBillstatus(-1);
            // 单据来源系统编码
            headvo.setSrc_syscode(17);
            // 合同金额
            // 结算组织
            headvo.setSett_org(headvo.getPk_org());
        } catch (Exception e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
        HYPubBO hybo1 = new HYPubBO();
        String org = hybo1.findColValue("org_adminorg", "pk_adminorg", " code = '" + headvo.getPk_org() + "' ") + "";
        // 根据BIP传的值进行创建自定义档案 def2	合同销售订单号
        // def6	合同编号
        // def3	标前项目号
        if (itemMaps.size() > 0) {
            NCLocator.getInstance().lookup(IDefdocService.class).insertDefdocs(headvo.getPk_org(), createDefVO(itemMaps.stream()
                    .map(map -> (String) map.get("def6"))
                    .collect(Collectors.toList()), "zdy-001", org));
        }
        if (itemMaps.size() > 0) {
            NCLocator.getInstance().lookup(IDefdocService.class).insertDefdocs(headvo.getPk_org(), createDefVO(itemMaps.stream()
                    .map(map -> (String) map.get("def2"))
                    .collect(Collectors.toList()), "BIP-ddh", org));
        }
        if (itemMaps.size() > 0) {
            NCLocator.getInstance().lookup(IDefdocService.class).insertDefdocs(headvo.getPk_org(), createDefVO(itemMaps.stream()
                    .map(map -> (String) map.get("def3"))
                    .collect(Collectors.toList()), "zdy-023", org));

            createProjectHeadVO(itemMaps, headvo.getPk_org().toString());
        }

        if (itemMaps != null && itemMaps.size() > 0) {
            for (Map<String, Object> item : itemMaps) {
                if (item.get("def7") != null) {
                    item.put("def7", item.get("def7").toString());
                }
                GatheringBillItemVO itemvo = (GatheringBillItemVO) fromJsonToVO(item, GatheringBillItemVO.class);

                try {
                    HYPubBO hybo = new HYPubBO();
                    itemvo.setRecaccount(headvo.getRecaccount());
                    // pk_balatype 结算方式 表头带出
                    itemvo.setPk_balatype(headvo.getPk_balatype());
                    // 票据类型 checktype 结算方式：银行承兑汇票-电子、银行承兑汇票-纸质=银行承兑汇票；商业承兑汇票-电子、商业承兑汇票-纸质=商业承兑汇票
                    String checktypeName = "";
                    if ("银行承兑汇票-电子".equals(balatypeName)) {
                        checktypeName = "电子银行承兑汇票";
                    } else if ("商业承兑汇票-电子".equals(balatypeName)) {
                        checktypeName = "电子商业承兑汇票";
                    } else if ("商业承兑汇票-纸质".equals(balatypeName)) {
                        checktypeName = "商业承兑汇票";
                    } else if ("银行承兑汇票-纸质".equals(balatypeName)) {
                        checktypeName = "银行承兑汇票";
                    }

                    if (checktypeName != "") {
                        Object checktypeCode = hybo.findColValue("bd_notetype", "code",
                                " name = '" + checktypeName + "' ");
                        itemvo.setChecktype(checktypeCode.toString());
                    }

                    // objtype 往来对象0-客户 2-部门 3-业务员 表头带出
                    itemvo.setObjtype(headvo.getObjtype());
                    // supplier 客户编码 表头带出
//					itemvo.setCustomer(headvo.getCustomer());
                    // pk_dept 部门编码 表头带出
                    itemvo.setPk_deptid(headvo.getPk_deptid());
                    // pk_psndoc 业务员编码 表头带出
                    itemvo.setPk_psndoc(headvo.getPk_psndoc());
                    // pk_currtype 币种编码 表头带出
                    itemvo.setPk_currtype(headvo.getPk_currtype());
                    // prepay 收款性质 默认应收款 0
                    itemvo.setPrepay(0);
                    //
                    UFDouble money_cr = itemvo.getMoney_cr();
                    UFDouble local_tax_cr = money_cr.multiply(ntaxrate).div(100);
                    itemvo.setLocal_tax_cr(local_tax_cr);
                    //
                    UFDouble notax_cr = money_cr.sub(local_tax_cr);
                    itemvo.setNotax_cr(notax_cr);
                    // zhangxinah增加组织本币无税金额(贷方)
                    itemvo.setLocal_notax_cr(notax_cr);
                    // 汇率为空时，默认为1
                    if (headvo.getRate() == null) {
                        itemvo.setRate(UFDouble.ONE_DBL);
                    } else {
                        itemvo.setRate(headvo.getRate());
                    }
                    //
                    itemvo.setTaxcodeid(ctaxcode);
                    //
                    itemvo.setTaxrate(ntaxrate);
                    // 收支项目
                    itemvo.setPk_subjcode("201");
                    money = money.add(itemvo.getMoney_cr());
                    itemvo.setLocal_money_cr(
                            itemvo.getMoney_cr().multiply(itemvo.getRate()).setScale(2, UFDouble.ROUND_HALF_UP));
                    Object def2 = itemvo.getDef2();
                    if (def2 != null)
                        itemvo.setDef2(hybo.findColValue("bd_defdoc", "pk_defdoc", " code = '" + def2 + "' ") + "");
                    Object def3 = itemvo.getDef3();
                    if (def3 != null)
                        itemvo.setDef3(hybo.findColValue("bd_defdoc", "pk_defdoc", " code = '" + def3 + "' ") + "");
                    Object def6 = itemvo.getDef6();
                    if (def6 != null)
                        itemvo.setDef6(hybo.findColValue("bd_defdoc", "pk_defdoc", " code = '" + def6 + "' ") + "");
//					Object def36 = itemvo.getDef36();
//					if (def36 != null)
//						itemvo.setDef36(hybo.findColValue("bd_defdoc", "pk_defdoc", " code = '" + def36 + "' ") + "");
                    // 新增自定义档案

                    HYSuperDMO dmo = new HYSuperDMO();
//					SaleOrderHVO[] hvo = (SaleOrderHVO[]) dmo.queryByWhereClause(SaleOrderHVO.class,
//							"vbillcode='" + def2 + "' and dr=0");
//					if (hvo == null || hvo.length == 0) {
//						throw new BusinessException("该销售订单在ERP中被删除，订单号：" + def2);
//					}
//					SaleOrderBVO[] bvos = (SaleOrderBVO[]) dmo.queryByWhereClause(SaleOrderBVO.class,
//							"csaleorderid='" + hvo[0].getPrimaryKey() + "'");
//					if (bvos != null) {
//						itemvo.setSrc_billid(bvos[0].getCsaleorderid());
//						itemvo.setSrc_itemid(bvos[0].getCsaleorderbid());
//						itemvo.setSrc_billtype("30");
//						itemvo.setSrc_tradetype(hvo[0].getVtrantypecode());
//						itemvo.setTop_billid(bvos[0].getCsaleorderid());
//						itemvo.setTop_itemid(bvos[0].getCsaleorderbid());
//						itemvo.setTop_billtype("30");
//					}

                } catch (Exception e) {
                    return ResultMessageUtil.exceptionToJSON(e);
                }

                itemvos.add(itemvo);
            }
        }

        headvo.setMoney(money);
        headvo.setGloballocal(money);
        // headvo.setRate(new UFDouble(1));
        headvo.setLocal_money(money.multiply(headvo.getRate()).setScale(2, UFDouble.ROUND_HALF_UP));
        AggGatheringBillVO bill = new AggGatheringBillVO();
        bill.setParentVO(headvo);
        bill.setChildrenVO((CircularlyAccessibleValueObject[]) itemvos.toArray(new GatheringBillItemVO[0]));
        try {
            Map<String, String> returnMap = ((IGatheringbillOpenService) NCLocator.getInstance()
                    .lookup(IGatheringbillOpenService.class)).saveBill(bill);
            JSONString resultJson = ResultMessageUtil.toJSON(returnMap);
            // 保存后动作
            JSONObject js_result = JSON.parseObject(resultJson.toJSONString());
            if (js_result.containsKey("success")) {
                if (js_result.getString("success").equals("true")) {
                    if (js_result.containsKey("data")) {
                        JSONObject js_data = js_result.getJSONObject("data");
                        String pk_gatherid = js_data.getString("pk_bill");
                        String pk_org = js_data.getString("pk_org");
                        GatheringBillItemVO[] billItemVOs = (GatheringBillItemVO[]) bill.getChildrenVO();
                        for (GatheringBillItemVO gatheringBillItemVO : billItemVOs) {
//							afterChangeMny(gatheringBillItemVO.getSrc_billid(), pk_org, billItemVOs[0].getDef6(),
//									pk_gatherid);
                        }
                    }
                }
            }
            return resultJson;
        } catch (BusinessException e) {
            return ResultMessageUtil.exceptionToJSON(e);
        }
    }

    private DefdocVO[] createDefVO(List<String> newhth, String defdoclistcode, String pk_org) throws BusinessException {
        String sql = " select pk_defdoclist from bd_defdoclist  where code='" + defdoclistcode + "' ";

        BaseDAO dao = new BaseDAO();
        String o = (String) dao.executeQuery(sql, new ColumnProcessor());
        HYPubBO hybo = new HYPubBO();

        ArrayList<DefdocVO> arrvo = new ArrayList<DefdocVO>();
        for (int i = 0; i < newhth.size(); i++) {

            Object pk_defdoc = hybo.findColValue("bd_defdoc", "pk_defdoc", " code = '" + newhth.get(i) + "' ");
            if (pk_defdoc != null) {
                continue;
            }
            DefdocVO vo = new DefdocVO();
            vo.setEnablestate(2);
            vo.setPk_defdoclist(o);
            vo.setPk_org(pk_org);
            vo.setCode(newhth.get(i));
            vo.setName(newhth.get(i));
            vo.setDataoriginflag(0);
            vo.setDr(0);
            vo.setPk_group(InvocationInfoProxy.getInstance().getGroupId());
            vo.setCreator(InvocationInfoProxy.getInstance().getUserId());
            vo.setCreationtime(new UFDateTime());

            arrvo.add(vo);
        }

        return arrvo.toArray(new DefdocVO[arrvo.size()]);

    }

    private ProjectHeadVO[] createProjectHeadVO(List<Map<String, Object>> newhth, String pk_org) throws BusinessException {
        HYPubBO hybo = new HYPubBO();
        ArrayList<ProjectHeadVO> arrvo = new ArrayList<ProjectHeadVO>();
        for (int i = 0; i < newhth.size(); i++) {
            Object pk_project = hybo.findColValue("bd_project", "pk_project", " PROJECT_CODE = '" + (String) newhth.get(i).get("def6") + "' ");
            if (pk_project != null) {
                continue;
            }
            ProjectHeadVO vo = new ProjectHeadVO();
            vo.setEnablestate(2);
            vo.setPk_org(pk_org);
            vo.setProject_code((String) newhth.get(i).get("def6"));
            vo.setProject_name((String) newhth.get(i).get("def6") + (String) newhth.get(i).get("def36"));
            vo.setPk_eps(hybo.findColValue("pm_eps", "pk_eps", " eps_code = '" + 01 + "' ") + "");
            vo.setDr(0);
            vo.setPk_group(InvocationInfoProxy.getInstance().getGroupId());
            vo.setCreator(InvocationInfoProxy.getInstance().getUserId());
            vo.setCreationtime(new UFDateTime());
            NCLocator.getInstance().lookup(IProjectServiceForPu.class).insertProject(vo);

        }

        return arrvo.toArray(new ProjectHeadVO[arrvo.size()]);

    }

    /**
     * 根据收款银行账户带出银行类别
     *
     * @param recaccount 银行账户
     */
    private String getBankTypeByAccount(String recaccount) {
        if (StringUtils.isEmpty(recaccount) || "~".equals(recaccount)) {
            return "";
        }
        String strWhere = " accnum = '[accnum]' and enablestate = 2";
        strWhere = strWhere.replace("[accnum]", recaccount);
        try {
            BankAccbasVO[] vos = (BankAccbasVO[]) getSuperDMO().queryByWhereClause(BankAccbasVO.class, strWhere);
            if (vos != null && vos.length > 0) {
                Logger.error("pk_banktype = " + vos[0].getPk_banktype());
                return vos[0].getPk_banktype();
            }
        } catch (DAOException e) {
            Logger.error("getBankTypeByAccount-exp: " + e.getMessage(), e);
        }
        return null;
    }
}
