package com.kmall.common.controller.pay.data.open;

import com.fasterxml.jackson.databind.JsonNode;
import com.kmall.common.constant.Dict;
import com.kmall.common.entity.CusPayDataOpenEntity;
import com.kmall.common.entity.CusReqRecordEntity;
import com.kmall.common.entity.pay.data.open.GoodsInfo;
import com.kmall.common.entity.pay.data.open.PayExInfo;
import com.kmall.common.entity.pay.data.open.PayExchangeInfoHead;
import com.kmall.common.entity.pay.data.open.PayExchangeInfoLists;
import com.kmall.common.manager.tocus.CusPayDataSender;
import com.kmall.common.manager.websocket.Callback;
import com.kmall.common.manager.websocket.WsClient;
import com.kmall.common.service.CusPayDataOpenService;
import com.kmall.common.service.CusReqRecordService;
import com.kmall.common.utils.Constant;
import com.kmall.common.utils.JacksonUtils;
import com.kmall.common.utils.pay.data.open.cus.CusPropertiesBuilder;
import com.kmall.common.utils.pay.data.open.websocket.WebsocketPropertiesBuilder;
import jdk.nashorn.internal.ir.annotations.Ignore;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.util.*;

/**
 * 企业返回海关所需获取的支付相关实时数据
 *
 * @author Scott Chen
 * @since 1.0
 * 2018-12-21
 */
@Controller
public class RealTimeDataUp {
    private static final Logger logger = LoggerFactory.getLogger(RealTimeDataUp.class);

    @Autowired
    private CusReqRecordService cusReqRecordService;

    @Autowired
    private CusPayDataOpenService cusPayDataOpenService;

    /**
     * 返回海关数据
     * 使用定时器
     *
     * @return
     */
    @RequestMapping(value = "/cus/send")
    @ResponseBody
    public String send() {
        try {
            //获取待发送数据
            Map<String, Object> param = new HashMap<>();
            param.put("status", Dict.cusDateOpenStatus.item_0.getItem());
            List<CusReqRecordEntity> recordList = cusReqRecordService.queryList(param);
            if(recordList == null || recordList.size() <= 0) {
                logger.debug("未查找到待发送海关支付信息订单");
                return "未查找到待发送海关支付信息订单";
            }

            for (CusReqRecordEntity record : recordList) {
                CusPayDataOpenEntity cusPayDataOpen = cusPayDataOpenService.queryObjectByOrderNo(record.getOrderNo());
                if (cusPayDataOpen == null) {
                    logger.error("订单编号【" + record.getOrderNo() + "】未查找到发送海关信息");
                    continue;
                }
                //组装待发送数据
                PayExInfo payExInfo = buildData(record,cusPayDataOpen );

                String unSignStr = unSignStr(payExInfo);

                //unSignStr = "\"sessionID\":\"7c73b9-962f45c2-348439e6\"||\"payExchangeInfoHead\":\"{\"guid\":\"C4B0E1DB-7EFE-4C9D-9CE8-2FFB3884619A\",\"initalRequest\":\"request data\",\"initalResponse\":\"response data\",\"ebpCode\":\"4403160Z3Y\",\"payCode\":\"440316T004\",\"payTransactionId\":\"EMATO201812200305\",\"totalAmount\":100.01,\"currency\":\"142\",\"verDept\":\"3\",\"payType\":\"1\",\"tradingTime\":\"2018-12-20 13:33:20\",\"note\":\"批量订单，测试订单优化,生成多个so订单\"}\"||\"payExchangeInfoLists\":\"[{\"orderNo\":\"EMATO201812200305\",\"goodsInfo\":[{\"gname\":\"Nivea90g\",\"itemLink\":\"http://ai.k1net.com/search/index.htm?key=aaa\"},{\"gname\":\"Nivea2100g\",\"itemLink\":\"http://ai.k1net.com/search/index.htm?key=bbb\"}],\"recpAccount\":\"20000032506200012146872\",\"recpCode\":\"91440300MA5DGG1J0R\",\"recpName\":\"abccc\"}]\"||\"serviceTime\":\"1545646340365\"";
                logger.debug("unsign string: {}", unSignStr);


                final Map<String, String> map = new HashMap<>();

                /**
                 * 签名
                 * 在签名成功的回调方法中, 发送海关
                 */
                WsClient.sign(unSignStr, null, new Callback() {
                    @Override
                    public Object run(Object result) {
                        // 成功处理
                        String wsStr = (String) result;
                        logger.debug("ws result: {}", wsStr);

                        if (wsStr.indexOf(WebsocketPropertiesBuilder.instance().getCusSignMethod()) > 0) {

                            // 提取加签结果值
                            JsonNode infoNode;
                            JsonNode argsNode;
                            JsonNode dataNode;
                            String signValue = null;
                            String certNo = null;

                            try {
                                infoNode = JacksonUtils.objectMapper().readTree(wsStr);
                                argsNode = JacksonUtils.objectMapper().readTree(infoNode.get("_args").toString());

                                JsonNode blNode = JacksonUtils.objectMapper().readTree(argsNode.get("Result").toString());
                                if (blNode.isBoolean() && Boolean.valueOf(blNode.asText())) {

                                    dataNode = JacksonUtils.objectMapper().readTree(argsNode.get("Data").toString());
                                    if (dataNode != null) {
                                        if (dataNode.get(0).isTextual()) {
                                            signValue = dataNode.get(0).asText();
                                        }
                                        if (dataNode.get(1).isTextual()) {
                                            certNo = dataNode.get(1).asText();
                                        }
                                    }
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                                return null;
                            }

                            if (StringUtils.isBlank(signValue)) {
                                logger.debug("sign value is null: {}", signValue);
                                return null;
                            }
                            logger.debug("signValue: {}", signValue);

                            // 发送
                            String cusResp = CusPayDataSender.send(payExInfo, signValue);
                            // 处理海关返回结果
                            CusReqRecordEntity response = CusPayDataSender.response(cusResp, record);
                            cusReqRecordService.update(response);
                        }
                        return null;
                    }
                }, new Callback() {
                    @Override
                    public Object run(Object params) {
                        record.setStatus(Dict.cusDateOpenStatus.item_3.getItem());
                        record.setModTime(new Date());
                        cusReqRecordService.update(record);

                        // 失败处理
                        logger.error("数据签名失败");
                        map.put("nonSignStr", "failed");
                        Exception e = (Exception) params;
                        e.printStackTrace();
                        return null;
                    }
                });
            }

            return "发送海关支付信息订单【" + recordList.size() + "】条成功！";
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }


    /**
     * 组装待发送数据
     *
     * @return
     */
    public PayExInfo buildData(CusReqRecordEntity record, CusPayDataOpenEntity cusPayDataOpen) {
        PayExInfo payExInfo = new PayExInfo();
        PayExchangeInfoHead head = new PayExchangeInfoHead();
        List<PayExchangeInfoLists> infoList = new ArrayList<>();


        // head
        head.setGuid(UUID.randomUUID().toString().toUpperCase());

        // 按实际请求支付公司数据填报
        head.setInitalRequest(cusPayDataOpen.getInitalRequest());
        // 按实际支付公司返回数据填报
        head.setInitalResponse(cusPayDataOpen.getInitalResponse());


        // 电商平台代码, 中网科技（深圳）有限公司
        head.setEbpCode(CusPropertiesBuilder.instance().getEbpCode());
        // 支付企业代码, 财付通支付科技有限公司
        head.setPayCode(CusPropertiesBuilder.instance().getPayCode());
        // 交易流水号
        head.setPayTransactionId(cusPayDataOpen.getPayTransactionId());
        // 交易金额
        head.setTotalAmount(cusPayDataOpen.getTotalAmount().doubleValue());
        // 币制
        head.setCurrency(cusPayDataOpen.getCurrency());
        // 验核机构, 1-银联 2-网联 3-其他
        head.setVerDept(cusPayDataOpen.getVerDept());
        // 支付类型, 1-APP 2-PC 3-扫码 4-其他
        head.setPayType(cusPayDataOpen.getPayType());
        // 交易成功时间
        head.setTradingTime(cusPayDataOpen.getTradingTime());
        // 备注
        head.setNote(cusPayDataOpen.getNote());


        // for 循环 --------------------
        List<GoodsInfo> goods = new ArrayList<>();

        // goodsInfo
        for (GoodsInfo info : cusPayDataOpen.getGoodsInfoList()) {
            GoodsInfo goodsInfo = new GoodsInfo();
            goodsInfo.setGname(info.getGname());
            goodsInfo.setItemLink(CusPropertiesBuilder.instance().getItemLink() + "?id=" + info.getItemLink());
            goods.add(goodsInfo);
        }

        // list
        PayExchangeInfoLists payExInfoList = new PayExchangeInfoLists();
        payExInfoList.setOrderNo(record.getOrderNo());
        payExInfoList.setGoodsInfo(goods);
        // 收款账号
        payExInfoList.setRecpAccount(CusPropertiesBuilder.instance().getRecpAccount());
        // 收款企业代码（境内企业为统一社会信用代码；境外企业可不填写）
        payExInfoList.setRecpCode(CusPropertiesBuilder.instance().getRecpCode());
        // 收款企业名称
        payExInfoList.setRecpName(CusPropertiesBuilder.instance().getRecpName());

        infoList.add(payExInfoList);

        // --------------------------------------------------

        // 海关请求数据时的sessionID
        payExInfo.setSessionID(record.getSessionID());

        payExInfo.setPayExchangeInfoHead(head);
        payExInfo.setPayExchangeInfoLists(infoList);
        payExInfo.setServiceTime(String.valueOf(System.currentTimeMillis()));

        return payExInfo;
    }



    public String unSignStr(PayExInfo payExInfo) {
        String result = "\"sessionID\":\"" + payExInfo.getSessionID() + "\""
                + "||\"payExchangeInfoHead\":\"" + JacksonUtils.toJson(payExInfo.getPayExchangeInfoHead()) + "\""
                + "||\"payExchangeInfoLists\":\"" + JacksonUtils.toJson(payExInfo.getPayExchangeInfoLists()) + "\""
                + "||\"serviceTime\":\"" + payExInfo.getServiceTime() + "\"";

        return result;
    }




}
