package com.hzya.frame.bip.v3.v2207.dps.service.impl;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hzya.frame.bip.v3.v2207.dps.service.IPayMentService;
import com.hzya.frame.dateutil.DateUtil;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;


@Service(value = "payMentServiceImpl")
public class PayMentServiceImpl implements IPayMentService {

    private static final Logger logger = LoggerFactory.getLogger(PayMentServiceImpl.class);

    private static  final String NAME="admin";
    private static final String PASSWORD="aHRzejg4OA==";
    private static final String CFSURL="http://101.132.140.208:26883/erp/services/";//测试端口:26893,正式端口:26883

    /**
     *
     * @content 杭泰OA付款单传递CFS 注：付款单，资金归集，资金拨付，同名账户划转和借款单都用同一个接口
     * @Param
     * @Return
     * @Author hecan
     * @Date 2023/10/13 10:40
     * **/
    public String sendOAPayMentToCFS(JSONObject jsonStr,String type){
        logger.info("开始执行杭泰OA付款单传递CFS");
        try {
        String cfsToken = sendCFSToken(NAME, PASSWORD);
        if(null!=cfsToken) {
            String jsonStrObj = jsonStr.getString("jsonStr");
            JSONObject jsonObjectMain = JSON.parseObject(jsonStrObj);
            String erpVoucherNo = jsonObjectMain.getString("erpVoucherNo");//OA主键
            String purpose = jsonObjectMain.getString("purpose");//摘要
            String isForindividual = "0";//是否对私付款
            StringBuffer stringBuffer = new StringBuffer();
            String documentType=null;
            switch (type){
                case "pay"://付款单
                    documentType="01";
                    break;
                case "fundc"://资金归集
                    documentType="02";
                    break;
                case "funda"://资金拨付
                    documentType="03";
                    break;
                case "acc"://同名账户划转
                    documentType="04";
                    break;
                case "loan"://借款单
                    documentType="05";
                    break;
                default:
                    break;
            }
            JSONArray jsonStrList = jsonObjectMain.getJSONArray("details");
            if (null != jsonStrList && jsonStrList.size() > 0) {
                for (Object seeyonEntity : jsonStrList) {
                    JSONObject jsonObjectFormson = JSON.parseObject(JSON.toJSONString(seeyonEntity));
                    String payerAccName = jsonObjectFormson.getString("payerAccName");//转出方账户名(付款账户)
                    String payerAccNo = jsonObjectFormson.getString("payerAccNo");//转出方账号(付款账号)
                    String curCode = jsonObjectFormson.getString("curCode");//付款方币种
                    String payeeAccName = jsonObjectFormson.getString("payeeAccName");//收款人帐户名称
                    String payeeAccNo = jsonObjectFormson.getString("payeeAccNo");//收款方账户号
                    BigDecimal amount = jsonObjectFormson.getBigDecimal("amount");//发生额
                    String payeeBankCode = jsonObjectFormson.getString("payeeBankCode");//联行号
                    String isQuick = jsonObjectFormson.getString("isQuick");//加急标志
                    String payType = jsonObjectFormson.getString("payType");//结算方式
                    String businessType = jsonObjectFormson.getString("businessType");//业务类别
                    stringBuffer.append("<map>\n");
                    stringBuffer.append("<documentType>" + nullConvert(documentType) + "</documentType>\n");
                    stringBuffer.append("<erpVoucherNo>" + nullConvert(erpVoucherNo) + "</erpVoucherNo>\n");
                    //stringBuffer.append("<payerAccName>"+"浙江杭泰数智能源开发有限公司"+"</payerAccName>\n");
                    stringBuffer.append("<payerAccName>"+nullConvert(payerAccName)+"</payerAccName>\n");
                    //stringBuffer.append("<payerAccNo>" +"71010122002702903"+ "</payerAccNo>\n");
                    stringBuffer.append("<payerAccNo>" + nullConvert(payerAccNo) + "</payerAccNo>\n");
                    stringBuffer.append("<curCode>" + nullConvert(curCode) + "</curCode>\n");
                    stringBuffer.append("<payeeAccName>" + nullConvert(payeeAccName) + "</payeeAccName>\n");
                    stringBuffer.append("<payeeAccNo>" + nullConvert(payeeAccNo) + "</payeeAccNo>\n");
                    stringBuffer.append("<amount>" + nullConvert(String.valueOf(amount)) + "</amount>\n");
                    //stringBuffer.append("<payeeBankCode>"+"301331000029"+"</payeeBankCode>\n");
                    stringBuffer.append("<payeeBankCode>"+nullConvert(payeeBankCode)+"</payeeBankCode>\n");
                    stringBuffer.append("<isQuick>" + nullConvert(isQuick) + "</isQuick>\n");
                    stringBuffer.append("<isForindividual>" + nullConvert(isForindividual) + "</isForindividual>\n");
                    stringBuffer.append("<payType>" + nullConvert(payType) + "</payType>\n");
                    stringBuffer.append("<purpose>" + nullConvert(purpose) + "</purpose>\n");
                    stringBuffer.append("<businessType>" + nullConvert(businessType) + "</businessType>\n");
                    stringBuffer.append("<debitByCustomer>" + nullConvert(jsonObjectFormson.getString("debitByCustomer")) + "</debitByCustomer>\n");//借方客商辅助核算编码
                    stringBuffer.append("<debitByBankAcc>" + nullConvert(payeeAccNo) + "</debitByBankAcc>\n");//借方银行账户辅助核算编码
                    stringBuffer.append("<debitByPersonnel>" + nullConvert(jsonObjectFormson.getString("debitByPersonnel")) + "</debitByPersonnel>\n");//借方人员辅助核算编码
                    stringBuffer.append("<creditByCustomer>" + nullConvert(jsonObjectFormson.getString("creditByCustomer")) + "</creditByCustomer>\n");//贷方客商辅助核算编码
                    stringBuffer.append("<creditByBankAcc>" + nullConvert(payerAccNo) + "</creditByBankAcc>\n");//贷方银行辅助核算编码
                    stringBuffer.append("</map>\n");
                }
            } else {
                stringBuffer.append("<map>\n");
                stringBuffer.append("<erpVoucherNo>" + nullConvert(erpVoucherNo) + "</erpVoucherNo>");
                stringBuffer.append("<purpose>" + nullConvert(purpose) + "</purpose>");
                stringBuffer.append("<isForindividual>" + nullConvert(isForindividual) + "</isForindividual>");
                stringBuffer.append("</map>\n");
            }
            String result=null;
            String xml= requestXML(cfsToken,"BkPaymentMainExchange",stringBuffer,"OA付款单同步发送");
            String url = "HTSZ_OA_BkPaymentMainWebService?wsdl";
            switch (type){
                case "pay"://付款单
                    logger.info("OA付款单发送CFS的请求参数为:{}", xml);
                     result = HttpRequest.post(CFSURL+url).header("Content-Type", "soap/xml").timeout(30000).body(xml).execute().body();
                    logger.info("OA付款单发送CFS的返回参数为:{}", result);
                    break;
                case "fundc"://资金归集
                    logger.info("OA资金归集发送CFS的请求参数为:{}", xml);
                     result = HttpRequest.post(CFSURL+url).header("Content-Type", "soap/xml").timeout(30000).body(xml).execute().body();
                    logger.info("OA资金归集发送CFS的返回参数为:{}", result);
                    break;
                case "funda"://资金调拨
                    logger.info("OA资金拨付发送CFS的请求参数为:{}", xml);
                     result = HttpRequest.post(CFSURL+url).header("Content-Type", "soap/xml").timeout(30000).body(xml).execute().body();
                    logger.info("OA资金拨付发送CFS的返回参数为:{}", result);
                    break;
                case "acc"://同名账户划转
                    logger.info("OA同名账户划转发送CFS的请求参数为:{}", xml);
                     result = HttpRequest.post(CFSURL+url).header("Content-Type", "soap/xml").timeout(30000).body(xml).execute().body();
                    logger.info("OA同名账户划转发送CFS的返回参数为:{}", result);
                    break;
                case "loan"://借款单
                    logger.info("OA借还款发送CFS的请求参数为:{}", xml);
                     result = HttpRequest.post(CFSURL+url).header("Content-Type", "soap/xml").timeout(30000).body(xml).execute().body();
                    logger.info("OA借还款发送CFS的返回参数为:{}", result);
                    break;
                default:
                    break;
            }
            return analyzeXML(result,"pay");
        }else{
            logger.info("请先登录CFS登录接口获取Token");
            return null;
        }
    } catch (Exception e) {
        e.printStackTrace();
        logger.info("杭泰OA付款单传递CFS错误，原因为:{}", e.getMessage());
    }
        return null;
    }

    /**
     *
     * @content 获取CFS登录校验码
     * @Param
     * @Return
     * @Author hecan
     * @Date 2023/10/13 15:38
     * **/
    public String sendCFSToken(String name,String password)  {
        try {
            String xml="<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:mdm=\"http://mdmData.server.webservice.banck.com\">\n" +
                    "   <soap:Header/>\n" +
                    "   <soap:Body>\n" +
                    "      <mdm:intoPaymentDataXml>\n" +
                    "         <!--Optional:-->\n" +
                    "         <mdm:xml>\n" +
                    "         <![CDATA[\n" +
                    "           <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                    "<message>\n" +
                    "<head>\n" +
                    "<transCode>LogOn</transCode>\n" +
                    "<erpTimestamp>"+DateUtil.dateToString(new Date(), "yyyy-MM-dd HH:mm:ss")+"</erpTimestamp>\n" +
                    "<sourcePlat>OA</sourcePlat>\n" +
                    "<desPlat>CFS</desPlat>\n" +
                    "<rmk>OA登录验证发送</rmk>\n" +
                    "</head>\n" +
                    "<body>\n" +
                    "<user>"+name+"</user>\n" +
                    "<password>"+password+"</password>\n" +
                    "</body>\n" +
                    "</message>\n" +
                    "         ]]>\n" +
                    "         </mdm:xml>\n" +
                    "      </mdm:intoPaymentDataXml>\n" +
                    "   </soap:Body>\n" +
                    "</soap:Envelope>";
            logger.info("CFS登录的请求参数为:{}",xml);
            String url="HTSZ_OA_LogOnWebService?wsdl";
            String result = HttpRequest.post(CFSURL+url).header("Content-Type", "soap/xml").timeout(30000).body(xml).execute().body();
            logger.info("CFS登录的返回参数为:{}",result);
            return analyzeXML(result,"login");
        }catch (Exception e){
            e.printStackTrace();
            logger.info("获取CFS登录失败，原因为:{}",e.getMessage());
        }
        return null;
    }

    /**
     *
     * @content 获取杭泰OA报销单传递CFS
     * @Param
     * @Return
     * @Author hecan
     * @Date 2023/10/16 16:17
     * **/
    @Override
    public String sendExpenseToCFS(JSONObject jsonStr) {
        logger.info("开始执行杭泰OA报销单传递CFS");
        try {
            String token = sendCFSToken(NAME, PASSWORD);
            if(null != token){
                String jsonStrObj = jsonStr.getString("jsonStr");
                JSONObject jsonObjectMain = JSON.parseObject(jsonStrObj);
                String erpVoucherNo = jsonObjectMain.getString("erpVoucherNo");//OA主键
                String purpose = jsonObjectMain.getString("purpose");//摘要
                StringBuffer stringBuffer = new StringBuffer();
                JSONArray jsonStrList = jsonObjectMain.getJSONArray("details");
                if(null != jsonStrList && jsonStrList.size()>0){
                    for (Object o : jsonStrList) {
                        JSONObject jsonObjectDetails = JSON.parseObject(JSON.toJSONString(o));
                                String payerAccName = jsonObjectDetails.getString("payerAccName");//转出方账户名(付款账户)
                                String payerAccNo = jsonObjectDetails.getString("payerAccNo");//转出方账号(付款账号)
                                String curCode = jsonObjectDetails.getString("curCode");//付款方币种
                                String payeeAccName = jsonObjectDetails.getString("payeeAccName");//收款人帐户名称
                                String payeeAccNo = jsonObjectDetails.getString("payeeAccNo");//收款方账户号
                                BigDecimal amount = jsonObjectDetails.getBigDecimal("amount");//发生额
                                String payeeBankCode = jsonObjectDetails.getString("payeeBankCode");//联行号
                                String isQuick = jsonObjectDetails.getString("isQuick");//加急标志
                                String payType = jsonObjectDetails.getString("payType");//结算方式
                                stringBuffer.append("<map>\n");
                                stringBuffer.append("<erpVoucherNo>" + nullConvert(erpVoucherNo) + "</erpVoucherNo>\n");
                                stringBuffer.append("<payerAccName>" + nullConvert(payerAccName) + "</payerAccName>\n");
                                //stringBuffer.append("<payerAccName>"+"浙江杭泰数智能源开发有限公司"+"</payerAccName>\n");
                                stringBuffer.append("<payerAccNo>" + nullConvert(payerAccNo) + "</payerAccNo>\n");
                                //stringBuffer.append("<payerAccNo>" +"71010122002702903"+ "</payerAccNo>\n");
                                stringBuffer.append("<curCode>" + nullConvert(curCode) + "</curCode>\n");
                                stringBuffer.append("<payeeAccName>" + nullConvert(payeeAccName) + "</payeeAccName>\n");
                                stringBuffer.append("<payeeAccNo>" + nullConvert(payeeAccNo) + "</payeeAccNo>\n");
                                stringBuffer.append("<amount>" + nullConvert(String.valueOf(amount)) + "</amount>\n");
                                stringBuffer.append("<payeeBankCode>" + nullConvert(payeeBankCode) + "</payeeBankCode>\n");
                                //stringBuffer.append("<payeeBankCode>"+"301331000029"+"</payeeBankCode>\n");
                                stringBuffer.append("<isQuick>" + nullConvert(isQuick) + "</isQuick>\n");
                                stringBuffer.append("<payType>" + nullConvert(payType) + "</payType>\n");
                                stringBuffer.append("<purpose>" + nullConvert(purpose) + "</purpose>\n");
                                stringBuffer.append("</map>\n");
                            }
                        } else {
                            stringBuffer.append("<map>\n");
                            stringBuffer.append("<erpVoucherNo>" + erpVoucherNo + "</erpVoucherNo>\n");
                            stringBuffer.append("<purpose>" + purpose + "</purpose>\n");
                            stringBuffer.append("</map>\n");
                        }
               String xml= requestXML(token,"BkExpenseExchange",stringBuffer,"OA费用报销单同步发送");
                logger.info("OA报销单发送CFS的请求参数为:{}", xml);
                String url = "HTSZ_OA_BkExpenseWebService?wsdl";
                String result = HttpRequest.post(CFSURL+url).header("Content-Type", "soap/xml").timeout(30000).body(xml).execute().body();
                logger.info("OA报销单发送CFS的返回参数为:{}", result);
                return analyzeXML(result,"pay");
            }
        }catch (Exception e){
            logger.info("杭泰OA报销单传递CFS错误，原因为:{}", e.getMessage());
        }
        return null;
    }

    //null转成空字符串
    private static String nullConvert(String str){
        if (null == str){
            return "";
        }
        return str;
    }

    private String requestXML(String token,String code,StringBuffer stringBuffer,String remark){
        String xml = "<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:mdm=\"http://mdmData.server.webservice.banck.com\">\n" +
                "   <soap:Header/>\n" +
                "   <soap:Body>\n" +
                "      <mdm:intoPaymentDataXml>\n" +
                "         <!--Optional:-->\n" +
                "         <mdm:xml>\n" +
                "         <![CDATA[\n" +
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<message>\n" +
                "<head>\n" +
                "<transCode>" + code + "</transCode>\n" +
                "<erpTimestamp>" + DateUtil.dateToString(new Date(), "yyyy-MM-dd HH:mm:ss") + "</erpTimestamp>\n" +
                "<sourcePlat>OA</sourcePlat>\n" +
                "<desPlat>CFS</desPlat>\n" +
                "<rmk>" + remark + "</rmk>\n" +
                "<sessionId>" + token + "</sessionId>\n" +
                "</head>\n" +
                "<body>\n" +
                "<list>\n";
        if (stringBuffer != null) {
            xml += stringBuffer.toString();
            xml += "</list>\n" +
                    "</body>\n" +
                    "</message>\n" +
                    " ]]>\n" +
                    "         </mdm:xml>\n" +
                    "      </mdm:intoPaymentDataXml>\n" +
                    "   </soap:Body>\n" +
                    "</soap:Envelope>";
        } else {
            xml += "</list>\n" +
                    "</body>\n" +
                    "</message>\n" +
                    "]]>\n" +
                    "         </mdm:xml>\n" +
                    "      </mdm:intoPaymentDataXml>\n" +
                    "   </soap:Body>\n" +
                    "</soap:Envelope>";
        }
        return xml;
    }

    /**
     *
     * @content 解析CFS返回的xml格式
     * @Param
     * @Return
     * @Author hecan
     * @Date 2023/10/19 14:07
     * **/
    private static  String analyzeXML(String result,String type){
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            org.w3c.dom.Document document = builder.parse(new InputSource(new StringReader(result)));
            org.w3c.dom.Element bodyElement = (org.w3c.dom.Element) document.getElementsByTagName("ns:return").item(0);
            if (null!=bodyElement) {
                String textContent = bodyElement.getTextContent();
                Document documentContext = DocumentHelper.parseText(textContent);
                Element rootElement = documentContext.getRootElement();
                Element body = rootElement.element("body");
                if (null != body) {
                    switch (type) {
                        case "login"://登录
                            Element sessionId = body.element("sessionId");
                            if (null != sessionId) {
                                logger.info("CFS登录的登录校验码为:{}", sessionId.getText());
                                return sessionId.getText();
                            } else {
                                logger.info("CFS登录的登录校验码没有获取到，请重新获取");
                                return null;
                            }
                        case "pay"://付款单和报销单
                            Element list = body.element("list");
                            List<Element> elements = list.elements();
                            String serialNo = null;
                            String statusMsg = null;
                            String erpVoucherNoCfs = null;
                            for (Element element : elements) {
                                serialNo = element.element("serialNo").getText();
                                statusMsg = element.element("statusMsg").getText();
                                erpVoucherNoCfs = element.element("erpVoucherNo").getText();
                            }
                            JSONObject jsonObject=new JSONObject();
                            jsonObject.put("erpVoucherNoCfs",erpVoucherNoCfs);
                            jsonObject.put("statusMsg",statusMsg);
                            jsonObject.put("serialNo",serialNo);
                            //return "当前单据：" + erpVoucherNoCfs + ",传递CFS返回信息:" + statusMsg + ",流水号:" + serialNo;
                            return jsonObject.toJSONString();
                        default:
                            break;
                    }
                }
            }
        }catch (Exception e){
            logger.info("解析CFS返回的xml格式错误:{}",e.getMessage());
        }
        return null;
    }


}
