package com.hfkj.channel.tianque.service;

import com.alibaba.fastjson.JSONObject;
import com.hfkj.channel.tianque.config.TianQueConfig;
import com.hfkj.channel.tianque.utils.RequestUtil;
import com.hfkj.common.exception.ErrorCode;
import com.hfkj.common.exception.ErrorHelp;
import com.hfkj.common.exception.SysCode;
import com.hfkj.common.utils.DateUtil;
import com.hfkj.config.CommonSysConst;
import com.hfkj.entity.*;
import com.hfkj.service.*;
import com.hfkj.sysenum.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @className: TianQueTradeService
 * @author: HuRui
 * @date: 2023/9/4
 **/
@Component
public class TianQueTradeService {

    private static Logger log = LoggerFactory.getLogger(TianQueTradeService.class);
    @Resource
    private BsTradeOrderService tradeOrderService;
    @Resource
    private BsTradeOrderMsgService tradeOrderMsgService;
    @Resource
    private BsMerPlatformNoService merPlatformNoService;
    @Resource
    private BsTradeOrderRefundService tradeOrderRefundService;
    @Resource
    private BsMerService merService;

    /**
     * 交易【主扫】
     * @param tradeNo 订单号
     * @return
     */
    public Map<String, Object> preorder(String tradeNo) {
        log.info("========= Start 交易【主扫】 Start ===========");
        // 查询交易订单
        BsTradeOrder order = tradeOrderService.getOrderByOutTradeNo(tradeNo);
        if (order == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到交易订单");
        }
        if (!order.getStatus().equals(TradeOrderStatusEnum.status1.getNumber())) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "订单不处于待支付状态");
        }
        // 查询商户号
        BsMerPlatformNo platformNo = merPlatformNoService.getPlatformNo(order.getMerId(), PlatformTypeEnum.type5);
        if (platformNo == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到商户号");
        }
        // 查询商户
        BsMer mer = merService.getMer(order.getMerId());
        if (mer == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的商户信息");
        }
        Map<String,Object> param = new HashMap<>();
        param.put("mno", platformNo.getPlatformNo());
        param.put("ordNo", order.getOutTradeNo());
        param.put("amt", order.getTradeActualAmount());
        param.put("payType", order.getPayMode());
        param.put("payWay", "02");
        if (StringUtils.isNotBlank(order.getSubject())) {
            param.put("subject", order.getSubject());
        } else {
            param.put("subject", mer.getMerAbbreviate());
        }
        if (StringUtils.isNotBlank(order.getRequestIp())) {
            param.put("trmIp", order.getRequestIp());
        } else {
            param.put("trmIp", "0.0.0.0");
        }
        if (order.getTimeoutExpress() != null) {
            param.put("timeExpire", order.getTimeoutExpress());
        }
        if (order.getPayMode().equals(TradeOrderPayModeEnum.WECHAT.getCode())) {
            if (StringUtils.isBlank(order.getPayAppid())) {
                param.put("subAppid", "wxa075e8509802f826");
            } else {
                param.put("subAppid", order.getPayAppid());
            }
        }
        param.put("userId", order.getPayUserId());
        param.put("ledgerAccountFlag", "01");  // 异步分账类型 00 异步分账,01 不分账,04 多次分账
        if (order.getCreateType() != null && order.getCreateType().equals(TradeOrderCreateTypeEnum.type3.getCode())) {
            param.put("notifyUrl", CommonSysConst.getSysConfig().getTianque_open_api_pay_notify_url());
        } else {
            param.put("notifyUrl", CommonSysConst.getSysConfig().getTianque_micro_pay_ret_url());
        }

        // 请求记录
        log.info("请求参数：", JSONObject.toJSONString(param));
        BsTradeOrderMsg orderMsg = new BsTradeOrderMsg();
        orderMsg.setOutTradeNo(tradeNo);
        orderMsg.setType(TradeOrderMsgTypeEnum.type1.getNumber());
        orderMsg.setRequestContent(JSONObject.toJSONString(param));
        tradeOrderMsgService.editTradeOrderMsg(orderMsg);

        JSONObject response = null;
        if (order.getTransType().equals("JSAPI")) {
            response = RequestUtil.request(TianQueConfig.requestUrl + "/order/jsapiScan", param);

        } else if (order.getTransType().equals("NATIVE")) {
            response = RequestUtil.request(TianQueConfig.requestUrl + "/order/activePlusScan", param);
        }
        orderMsg.setResponseContent(response.toJSONString());
        tradeOrderMsgService.editTradeOrderMsg(orderMsg);
        if (!"0000".equals(response.getString("bizCode"))) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, response.getString("bizMsg"));
        }

        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("order", order);
        returnMap.put("payMode", order.getPayMode());
        returnMap.put("platformType", PlatformTypeEnum.type5.getNumber());

        Map<String, Object> payParam = new HashMap<>();

        Map<String, Object> accRespFields = new HashMap<>();
        accRespFields.put("nonce_str", StringUtils.isNotBlank(response.getString("paynonceStr"))?response.getString("paynonceStr"):"");
        accRespFields.put("code", StringUtils.isNotBlank(response.getString("payUrl"))?response.getString("payUrl"):"");
        accRespFields.put("package", StringUtils.isNotBlank(response.getString("payPackage"))?response.getString("payPackage"):"");
        accRespFields.put("form_data", "");
        accRespFields.put("time_stamp", StringUtils.isNotBlank(response.getString("payTimeStamp"))?response.getString("payTimeStamp"):"");
        accRespFields.put("code_image", "");
        accRespFields.put("app_id", StringUtils.isNotBlank(response.getString("payAppId"))?response.getString("payAppId"):"");
        accRespFields.put("sign_type", StringUtils.isNotBlank(response.getString("paySignType"))?response.getString("paySignType"):"");
        accRespFields.put("redirect_url", StringUtils.isNotBlank(response.getString("redirectUrl"))?response.getString("redirectUrl"):"");
        accRespFields.put("best_pay_info", "");
        String prepay_id = "";
        if (StringUtils.isNotBlank(response.getString("prepayId"))) {
            prepay_id = response.getString("prepayId");

        } else if (StringUtils.isNotBlank(response.getString("source"))) {
            prepay_id = response.getString("source");

        }
        accRespFields.put("prepay_id", prepay_id);
        accRespFields.put("pay_sign", StringUtils.isNotBlank(response.getString("paySign"))?response.getString("paySign"):"");
        payParam.put("acc_resp_fields", accRespFields);

        returnMap.put("payParam", JSONObject.parseObject(JSONObject.toJSONString(payParam)));
        log.info("========= END 交易【主扫】 END ===========");

        return returnMap;
    }

    /**
     * 查询交易
     * @param tradeNo 订单号
     */
    public JSONObject queryTrade(String tradeNo) {
        log.info("========= Start 交易查询 Start ===========");
        try {
            // 查询交易订单
            BsTradeOrder order = tradeOrderService.getOrderByOutTradeNo(tradeNo);
            if (order == null) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到交易订单");
            }
            Map<String,Object> param = new HashMap<>();
            param.put("mno", order.getPlatformMerNo());
            param.put("ordNo", order.getOutTradeNo());
            JSONObject response = RequestUtil.request(TianQueConfig.requestUrl + "/query/tradeQuery", param);
            if (!"0000".equals(response.getString("bizCode"))) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, response.getString("bizMsg"));
            }
            return response;
        } catch (Exception e) {
            return null;
        } finally {
            log.info("========= END 交易查询 END ===========");
        }
    }

    /**
     * 手续费查询
     * @param tradeNo 订单号
     */
    public JSONObject poundageQuery(String merNo,String tradeNo) {
        log.info("========= Start 手续费查询 Start ===========");
        try {
            Map<String,Object> param = new HashMap<>();
            param.put("mno", merNo);
            param.put("ordNo", tradeNo);
            JSONObject response = RequestUtil.request(TianQueConfig.requestUrl + "/query/poundageQuery", param);
            if (!"0000".equals(response.getString("bizCode"))) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, response.getString("bizMsg"));
            }
            return response;
        } catch (Exception e) {
            return null;
        } finally {
            log.info("========= END 手续费查询 END ===========");
        }
    }

    /**
     * 退款
     * @param refundNo 订单号
     */
    public Map<String, Object> refund(String refundNo, BigDecimal refundAmount) {
        log.info("========= Start 交易退款 Start ===========");
        // 查询交易订单
        BsTradeOrderRefund orderRefund = tradeOrderRefundService.getRefundByRefundNo(refundNo);
        if (orderRefund == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到订单");
        }
        if (!orderRefund.getStatus().equals(TradeOrderRefundStatusEnum.status1.getNumber())) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "订单不处于退款中状态");
        }
        // 查询交易订单
        BsTradeOrder order = tradeOrderService.getOrderByOutTradeNo(orderRefund.getOutTradeNo());
        if (order == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到交易订单");
        }

        Map<String,Object> param = new HashMap<>();
        param.put("mno", order.getPlatformMerNo());
        param.put("ordNo", orderRefund.getRefundNo());
        param.put("origOrderNo", order.getOutTradeNo());
        param.put("amt", refundAmount);
        param.put("refundReason", orderRefund.getRefundReason());
        // param.put("notifyUrl", orderRefund.getRefundReason());
        JSONObject response = RequestUtil.request(TianQueConfig.requestUrl + "/order/refund", param);
        // 请求记录
        BsTradeOrderMsg orderMsg = new BsTradeOrderMsg();
        orderMsg.setOutTradeNo(refundNo);
        orderMsg.setType(TradeOrderMsgTypeEnum.type1.getNumber());
        orderMsg.setRequestContent(JSONObject.toJSONString(param));
        orderMsg.setResponseContent(response.toJSONString());
        tradeOrderMsgService.editTradeOrderMsg(orderMsg);

        if (!"0000".equals(response.getString("bizCode"))) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, response.getString("bizMsg"));
        }
 /*       // 是否分账
        if (order.getProfitSharingStatus().equals(true)) {
            // 查询分账记录
            BsTradeOrderProfitSharing tradeOrderProfitSharing = tradeOrderProfitSharingService.getProfitSharingByTradeOrderId(ProfitSharingCmdTypeEnum.CMD_TYPE_1, order.getId());
            if (tradeOrderProfitSharing != null && tradeOrderProfitSharing.getStatus().equals(ProfitSharingStatusEnum.status3.getNumber())) {
                laKaLaTradeSeparateService.cancel(tradeOrderProfitSharing.getProfitSharingOrderNo());
            }
        }*/

        orderRefund.setPlatformOrderNo(response.getString("uuid"));
        orderRefund.setAccTradeNo(response.getString("transactionId"));
        orderRefund.setTotalAmount(order.getTradeActualAmount());
        orderRefund.setRefundAmount(response.getBigDecimal("amt"));
        orderRefund.setPayerAmount(response.getBigDecimal("amt"));
        orderRefund.setSettleAmount(response.getBigDecimal("realRefundAmount"));
        orderRefund.setSettleDate(DateUtil.format(response.getString("clearDt"), "yyyyMMdd"));
        orderRefund.setRefundTime(new Date());
        orderRefund.setStatus(TradeOrderRefundStatusEnum.status2.getNumber());
        tradeOrderRefundService.editOrderRefund(orderRefund);

        order.setStatus(TradeOrderStatusEnum.status6.getNumber());
        tradeOrderService.editOrder(order);

        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("order", order);
        returnMap.put("orderRefund", orderRefund);
        log.info("========= END 交易退款 END ===========");
        return returnMap;
    }


    /**
     * 退款查询
     * @param refundNo 订单号
     */
    public Map<String, Object> refundQuery(String refundNo) {
        log.info("========= Start 退款查询 Start ===========");
        // 查询交易订单
        BsTradeOrderRefund orderRefund = tradeOrderRefundService.getRefundByRefundNo(refundNo);
        if (orderRefund == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到订单");
        }
        // 查询交易订单
        BsTradeOrder order = tradeOrderService.getOrderByOutTradeNo(orderRefund.getOutTradeNo());
        if (order == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到交易订单");
        }
        Map<String,Object> param = new HashMap<>();
        param.put("mno", order.getPlatformMerNo());
        param.put("ordNo", orderRefund.getRefundNo());
        JSONObject response = RequestUtil.request(TianQueConfig.requestUrl + "/query/refundQuery", param);
        if (!"0000".equals(response.getString("bizCode"))) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, response.getString("bizMsg"));
        }
        log.info("========= END 退款查询 END ===========");
        return response;
    }

    /**
     * 获取银联用户标识
     * @param userAuthCode 	授权码
     * @param paymentApp 银联支付标识
     */
    public JSONObject getUnionInfo(String userAuthCode,String paymentApp) {
        log.info("========= Start 获取银联用户标识 Start ===========");
        // 查询交易订单
        Map<String,Object> param = new HashMap<>();
        param.put("userAuthCode", userAuthCode);
        param.put("paymentApp", paymentApp);
        JSONObject response = RequestUtil.request(TianQueConfig.requestUrl + "/query/getUnionInfo", param);
        if (!"0000".equals(response.getString("bizCode"))) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, response.getString("bizMsg"));
        }
        log.info("========= END 获取银联用户标识 END ===========");
        return response;
    }

}
