package com.pj.task;

import cn.hutool.log.StaticLog;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.pj.api.client.level_one_server.LevelOneServerInterface;
import com.pj.api.client.level_two_server.LevelTwoServerInterface;
import com.pj.api.dto.BankInfoDto;
import com.pj.bank_byte.BankByte;
import com.pj.bank_byte.BankByteMapper;
import com.pj.bank_info.BankInfo;
import com.pj.bank_info.BankInfoMapper;
import com.pj.bank_info_charges.BankInfoCharges;
import com.pj.bank_info_charges.BankInfoChargesService;
import com.pj.common.core.utils.StringUtils;
import com.pj.enummj.FinishStatus;
import com.pj.rabbitmq.MessageSender;
import com.pj.utils.CryptoUtil;
import com.pj.utils.ht.AESUtil;
import com.pj.xml.MessageXML;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.IOException;
import java.io.StringReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Configuration
@EnableScheduling
@Transactional(rollbackFor = Exception.class)
public class BankByteTask {

    /**
     * 银行回执字节码mapper
     */
    @Autowired
    private BankByteMapper bankByteMapper;
    /**
     * 银行回执信息mapper
     */
    @Autowired
    private BankInfoMapper bankInfoMapper;
    /**
     * 银行回执信息-手续费
     */
    @Autowired
    private BankInfoChargesService bankInfoChargesService;

    @Autowired
    private LevelOneServerInterface levelOneServerInterface;
    @Autowired
    private LevelTwoServerInterface levelTwoServerInterface;

    @Autowired
    private MessageSender messageSender;


    /**
     * 启动定时任务
     */
    @Scheduled(cron = "*/10 * * * * ?")  // 每10秒扫描一次
    public void bankByteTask() throws ParserConfigurationException {
        StaticLog.info("\n  ----------------银行数据处理定时任务开始----------------------");

        //扫描表内是否有待处理任务
        List<BankByte> byteList = bankByteMapper.selectList(
                new LambdaQueryWrapper<BankByte>().eq(BankByte::getFinishStatus, FinishStatus.FINISH_STATUS_ZERO.getCode()).orderByAsc(BankByte::getCreateTime));
        //判断是否有任务,没有则返回
        if (byteList.size() == 0) {
            StaticLog.info("\n  ---  暂无待处理【银行回执信息】。" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "\n");
            return;
        }
        //执行任务处理流程
        for (BankByte item : byteList) {
            StaticLog.info("\n  ----------------执行任务处理流程----------------------\n" + item.toString());
            // 创建DOM解析器
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 创建XPath对象
            XPath xpath = XPathFactory.newInstance().newXPath();

            String body = item.getBody();
            if(!StringUtils.containsIgnoreCase(body,"<plain>")) {
                item.setFinishStatus(FinishStatus.FINISH_STATUS_TWO.getCode());
                bankByteMapper.updateById(item);
                continue;
            }
            String str = body.substring(body.indexOf("<plain>")+7, body.indexOf("</plain>"));
            //数据解析
            String decrypt = CryptoUtil.decrypt(str);
            String xmlStr = body.replace(str, decrypt);

            BankInfo bankInfo = new BankInfo();
            bankInfo.setCreateTime(new Date());

            boolean isMKT0035 = StringUtils.containsIgnoreCase(xmlStr,"MKT003") || StringUtils.containsIgnoreCase(xmlStr,"MKT005");
            boolean isMKT008 = StringUtils.containsIgnoreCase(xmlStr,"MKT008");
            boolean hasCommission = StringUtils.containsIgnoreCase(xmlStr, "<results xsi:type=\"orderResultDTO\"");

            //银行回执——headers——获取头部字段
            if(isMKT0035 || isMKT008){//二级市场-订单回执报文-头部处理
                String headersStr = xmlStr.substring(xmlStr.indexOf("<headers>"), xmlStr.indexOf("</headers>") + 10);
                try {
                    // 解析XML字符串，获取Document对象
                    Document document = builder.parse(new InputSource(new StringReader(headersStr)));

                    Element element = document.getDocumentElement();
                    NodeList childNodes = element.getChildNodes();
                    for (int i = 0; i < childNodes.getLength(); i++) {
                        Node node = childNodes.item(i);
                        if (node instanceof Element) {
                            Element ele = (Element) node;
                            String key = ele.getAttribute("key");
                            String substring = ele.getFirstChild() == null ? "" : ele.getFirstChild().getNodeValue();
                            if(StringUtils.containsIgnoreCase(key,"sn")) {
                                bankInfo.setSn(substring);
                            }
                            if(StringUtils.containsIgnoreCase(key,"date")) {
                                bankInfo.setDate(substring);
                            }
                            if(StringUtils.containsIgnoreCase(key,"organization")) {
                                bankInfo.setOrganization(substring);
                            }
                            if(StringUtils.containsIgnoreCase(key,"bankCode")) {
                                bankInfo.setBankCode(substring);
                            }
                            if(StringUtils.containsIgnoreCase(key,"operation")) {
                                bankInfo.setOperation(substring);
                            }
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (SAXException e) {
                    e.printStackTrace();
                }
            }
            else {//一级市场-订单回执报文-头部处理
                String headersStr = xmlStr.substring(xmlStr.indexOf("<headers>")+9, xmlStr.indexOf("</headers>"));
                String[] headersSplit = headersStr.split("</item>");
                for (String s : headersSplit) {
                    if(StringUtils.containsIgnoreCase(s,"sn")) {
                        String substring = s.substring(s.indexOf("<value>")+7, s.indexOf("</value>"));
                        bankInfo.setSn(substring);
                    }
                    if(StringUtils.containsIgnoreCase(s,"date")) {
                        String substring = s.substring(s.indexOf("<value>")+7, s.indexOf("</value>"));
                        bankInfo.setDate(substring);
                    }
                    if(StringUtils.containsIgnoreCase(s,"organization")) {
                        String substring = s.substring(s.indexOf("<value>")+7, s.indexOf("</value>"));
                        bankInfo.setOrganization(substring);
                    }
                    if(StringUtils.containsIgnoreCase(s,"bankCode")) {
                        String substring = s.substring(s.indexOf("<value>")+7, s.indexOf("</value>"));
                        bankInfo.setBankCode(substring);
                    }
                    if(StringUtils.containsIgnoreCase(s,"operation")) {
                        String substring = s.substring(s.indexOf("<value>")+7, s.indexOf("</value>"));
                        bankInfo.setOperation(substring);
                    }
                }
            }

            //银行回执——plain——获取responseDTO
            String payloadStr = xmlStr.substring(xmlStr.indexOf("<plain>")+7, xmlStr.indexOf("</plain>"));
            if(isMKT0035) {
                payloadStr = xmlStr.substring(xmlStr.indexOf("<plain>")+7, xmlStr.indexOf("<results xsi:type="));
                payloadStr += "</payload>";

                String resultsStr = "";
                if(StringUtils.containsIgnoreCase(xmlStr,"MKT003")) {
                    resultsStr = xmlStr.substring(xmlStr.indexOf("<results xsi:type=\"vendorDTO\""), xmlStr.indexOf("</payload>"));
                } else if(StringUtils.containsIgnoreCase(xmlStr,"MKT005")) {
                    resultsStr = xmlStr.substring(xmlStr.indexOf("<results xsi:type=\"vendeeDTO\""), xmlStr.indexOf("</payload>"));
                }

                try {
                    // 解析XML字符串，获取Document对象
                    Document document = builder.parse(new InputSource(new StringReader(payloadStr)));
                    Element element = document.getDocumentElement();

                    bankInfo.setCode(element.getAttribute("code"));
                    bankInfo.setSource(element.getAttribute("source"));
                    bankInfo.setNote(element.getAttribute("note"));

                    // 解析XML字符串，获取Document对象
                    Document document1 = builder.parse(new InputSource(new StringReader(resultsStr)));
                    Element element1 = document1.getDocumentElement();

                    bankInfo.setName(element1.getAttribute("name"));
                    bankInfo.setPapersType(element1.getAttribute("papersType"));
                    bankInfo.setPapersNo(element1.getAttribute("papersNo"));
                    bankInfo.setNationality(element1.getAttribute("nationality"));
                    bankInfo.setAccount(element1.getAttribute("accountNo"));
                    bankInfo.setPayBankCode(element1.getAttribute("bankCode"));
                    bankInfo.setTel(element1.getAttribute("tel"));

                } catch (SAXException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            else if(isMKT008) {
                try {
                    // 解析XML字符串，获取Document对象
                    Document document = builder.parse(new InputSource(new StringReader(payloadStr)));
                    Element element = document.getDocumentElement();

                    bankInfo.setCode(element.getAttribute("code"));
                    bankInfo.setType(element.getAttribute("type"));
                    bankInfo.setNote(element.getAttribute("note"));
                    bankInfo.setSource(element.getAttribute("source"));
                    bankInfo.setResult(element.getAttribute("result"));
                } catch (SAXException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            else {
                try {
                    // 解析XML字符串，获取Document对象
                    Document document = builder.parse(new InputSource(new StringReader(payloadStr)));

                    bankInfo.setCode(xpath.evaluate("/payload/code", document));
                    bankInfo.setSource(xpath.evaluate("/payload/source", document));
                    bankInfo.setResult(xpath.evaluate("/payload/result", document));
                    bankInfo.setNote(xpath.evaluate("/payload/note", document));
                    bankInfo.setType(xpath.evaluate("/payload/type", document));

                    bankInfo.setName(xpath.evaluate("/payload/name", document));
                    bankInfo.setPapersType(xpath.evaluate("/payload/papersType", document));
                    bankInfo.setPapersNo(xpath.evaluate("/payload/papersNo", document));
                    bankInfo.setNationality(xpath.evaluate("/payload/nationality", document));
                    bankInfo.setAccount(xpath.evaluate("/payload/account", document));
                    bankInfo.setPayBankCode(xpath.evaluate("/payload/bankCode", document));
                    bankInfo.setTel(xpath.evaluate("/payload/tel", document));

                } catch (SAXException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (XPathExpressionException e) {
                    e.printStackTrace();
                }
            }

            //保存银行回执信息
            int insert = bankInfoMapper.insert(bankInfo);

            boolean result = false;
            //边民备案验证查询
            if(bankInfo.getOperation().equalsIgnoreCase("SXB002")) {
                boolean r = levelOneServerInterface.getByidCard(bankInfo.getName(), bankInfo.getPapersNo());
                System.out.println("---------------SXB002="+r);
                if (r) {
                    log.info("send data to 银行:{}", JSON.toJSONString(bankInfo));
                    String xml = MessageXML.SXB003(bankInfo);
                    messageSender.sendToLevelOneMQ(xml);
                    log.info("send mq msg finish:{}", JSON.toJSONString(xml));
                } else {
                    log.info("send data to 银行:{}", JSON.toJSONString(bankInfo));
                    String xml = MessageXML.SXB004(bankInfo);
                    messageSender.sendToLevelOneMQ(xml);
                    log.info("send mq msg finish:{}", JSON.toJSONString(xml));
                }
                result = true;
            }
            //边民备案验证查询-银行回复新开户或变更数据
            else if(bankInfo.getOperation().equalsIgnoreCase("SXB005")) {
                BankInfoDto bankInfoDto = new BankInfoDto();
                BeanUtils.copyProperties(bankInfo, bankInfoDto);
                result = levelOneServerInterface.updateBySXB005(bankInfoDto);
            }
            //商铺备案验证查询
            else if(bankInfo.getOperation().equalsIgnoreCase("SXB006")) {
                boolean r = levelOneServerInterface.getByName(bankInfo.getName());
                System.out.println("---------------SXB006="+r);
                if (r) {
                    log.info("send data to 银行:{}", JSON.toJSONString(bankInfo));
                    String xml = MessageXML.SXB007(bankInfo);
                    messageSender.sendToLevelOneMQ(xml);
                    log.info("send mq msg finish:{}", JSON.toJSONString(xml));
                } else {
                    log.info("send data to 银行:{}", JSON.toJSONString(bankInfo));
                    String xml = MessageXML.SXB008(bankInfo);
                    messageSender.sendToLevelOneMQ(xml);
                    log.info("send mq msg finish:{}", JSON.toJSONString(xml));
                }
                result = true;
            }
            //商铺备案验证查询-银行回复新开户或变更数据
            else if(bankInfo.getOperation().equalsIgnoreCase("SXB009")) {
                BankInfoDto bankInfoDto = new BankInfoDto();
                BeanUtils.copyProperties(bankInfo, bankInfoDto);
                result = levelOneServerInterface.updateBySXB009(bankInfoDto);
            }
            //（一级市场）订单扣款-成功
            else if(bankInfo.getOperation().equalsIgnoreCase("SXB011")) {
                //参数：一级市场边民订单-订单编号
                result = levelOneServerInterface.confirmOrderFromBank(bankInfo.getSource(),bankInfo.getNote(),1);
            }
            //（一级市场）订单扣款-失败
            else if(bankInfo.getOperation().equalsIgnoreCase("SXB012")) {
                result = levelOneServerInterface.confirmOrderFromBank(bankInfo.getSource(),bankInfo.getNote(),2);
            }
            //（一级市场）订单退款-成功
            else if(bankInfo.getOperation().equalsIgnoreCase("SXB014")) {
                result = levelOneServerInterface.chargebackFromBank(bankInfo.getSource(),1, bankInfo.getNote());
            }
            //（一级市场）订单退款-失败
            else if(bankInfo.getOperation().equalsIgnoreCase("SXB015")) {
                result = levelOneServerInterface.chargebackFromBank(bankInfo.getSource(),2, bankInfo.getNote());
            }
            //（一级市场-通车批信息）订单打款-成功
            else if(bankInfo.getOperation().equalsIgnoreCase("SXB017")) {
                //参数：一级市场边民订单-订单编号, n个
                result = levelOneServerInterface.orderFinishFromBank(bankInfo.getSource(), 1);
            }
            //（一级市场-通车批信息）订单打款-失败
            else if(bankInfo.getOperation().equalsIgnoreCase("SXB018")) {
                result = levelOneServerInterface.orderFinishFromBank(bankInfo.getSource(), 2);
            }

            //（二级市场）卖家账号认证回执——101/102/110	110(未签约）
            else if(bankInfo.getOperation().equalsIgnoreCase("MKT003")) {
                if(bankInfo.getCode().equals("101")) {
                    result = true;
                }
            }
            //（二级市场）买家账号认证回执——103/104/110	110(未签约）
            else if(bankInfo.getOperation().equalsIgnoreCase("MKT005")) {
                if(bankInfo.getCode().equals("101")) {
                    result = true;
                }
            }
            //（二级市场）订单扣款            001：扣款订单    002：退款订单    003：打款订单
            else if(bankInfo.getOperation().equalsIgnoreCase("MKT008") && "001".equals(bankInfo.getType())) {
                if(!hasCommission) {//无手续费模式——采购商支付扣款
                    if("200".equals(bankInfo.getCode())) {//回执代码为200则表示支付成功
                        //参数：二级市场边民订单-订单编号
                        result = levelTwoServerInterface.payTax(bankInfo.getSource(),1);
                    } else {//支付失败
                        result = levelTwoServerInterface.payTax(bankInfo.getSource(),2);
                    }
                }
                else {//有手续费模式——边民缴税以及各服务费
                    if("200".equals(bankInfo.getCode())) {//回执代码为200则表示缴费成功
                        //参数：二级市场边民订单-订单编号
                        result = levelTwoServerInterface.payTaxFromBank(bankInfo.getSource(),1);
                    } else {//缴费失败
                        result = levelTwoServerInterface.payTaxFromBank(bankInfo.getSource(),2);
                    }
                }
            }
            //（二级市场）订单退款-----暂无调用订单退款
            //else if(bankInfo.getOperation().equalsIgnoreCase("MKT008") && "002".equals(bankInfo.getType())) { }

            //数据处理完成状态
            if(result) {//处理成功
                item.setFinishStatus(FinishStatus.FINISH_STATUS_ONE.getCode());
            } else {//处理失败
                item.setFinishStatus(FinishStatus.FINISH_STATUS_TWO.getCode());
            }
            bankByteMapper.updateById(item);

        };

    }

}
