package com.gree.mall.miniapp.logic.common;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.gree.mall.miniapp.constant.SybConstants;
import com.gree.mall.miniapp.enums.IsYesNoEnum;
import com.gree.mall.miniapp.enums.PayOrderTypeEnum;
import com.gree.mall.miniapp.enums.PayTypeEnum;
import com.gree.mall.miniapp.enums.material.PartsOrderStatusEnum;
import com.gree.mall.miniapp.enums.material.PartsPayFlagEnum;
import com.gree.mall.miniapp.exception.RemoteServiceException;
import com.gree.mall.miniapp.logic.material.parts.WebsitPartsSalesOrderLogic;
import com.gree.mall.miniapp.plus.entity.*;
import com.gree.mall.miniapp.plus.service.WebsitPartsSalesService;
import com.gree.mall.miniapp.plus.service.WebsitPartsWorkerCreditRecordService;
import com.gree.mall.miniapp.plus.service.WebsitSalesItemService;
import com.gree.mall.miniapp.plus.service.WebsitSalesService;
import com.gree.mall.miniapp.utils.ArithUtils;
import com.gree.mall.miniapp.utils.DateUtils;
import com.gree.mall.miniapp.utils.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Component
@Slf4j
public class AllInPayLogic {

    @Value("${allIn.payment.notifyUrl}")
    private String notifyUrl;
    @Value("${share.mall.appid}")
    private String mallAppid;

    @Resource
    CommonLogic commonLogic;
    @Resource
    WebsitSalesService websitSalesService;
    @Resource
    WebsitPartsSalesService websitPartsSalesService;
    @Resource
    WebsitPartsSalesOrderLogic websitPartsSalesOrderLogic;
    @Resource
    WebsitPartsWorkerCreditRecordService websitPartsWorkerCreditRecordService;
    @Resource
    WebsitSalesItemService websitSalesItemService;

    /**
     * 通联支付
     */
    public Map<String, String> serviceUnifiedOrder(WebsitSalesPayOrder order, String payType, String frontUrl)
            throws RemoteServiceException {
        Map<String, String> reqMap = new HashMap<>();
        reqMap.put("orgid", order.getOrgId());
        reqMap.put("cusid", order.getMchNo());
        reqMap.put("appid", order.getAppid());
        if (!SybConstants.PAY_TYPE_W01.equals(payType)) {
            reqMap.put("acct", order.getOpenid());
            reqMap.put("sub_appid", mallAppid);
        }
        reqMap.put("notify_url", this.notifyUrl);
        reqMap.put("trxamt", (int) ArithUtils.mul(order.getPayValue().doubleValue(), 100) + "");
        reqMap.put("reqsn", order.getOrderNo());
        reqMap.put("body", order.getWebsitName());
        reqMap.put("paytype", payType);
        reqMap.put("remark", order.getOrderId());
        reqMap.put("front_url", frontUrl);

        HashMap<String, String> heads = new HashMap();
        String token = commonLogic.getInfToken();
        if (StringUtils.isEmpty(token)) {
            throw new RemoteServiceException("获取接口令牌失败");
        }
        heads.put("authorization_token", token);

        String content = HttpUtils.requestPostBody(commonLogic.getInfUrl() + "/pay/csb/qrcode", JSON.toJSONString(reqMap), heads);

        Map<String, Object> resMap = JSON.parseObject(content, new TypeReference<HashMap<String, Object>>() {});

        if (!Optional.ofNullable(resMap.get("message")).orElse("error").toString().equals("success")) {
            log.error("通联统一支付接口执行失败: {}>>>{}", order.getOrderId(), resMap);
            throw new RemoteServiceException("通联统一支付接口执行失败：" + resMap.get("message"));
        }

        return (Map<String, String>) resMap.get("data");
    }

    /**
     * 通联支付查询订单
     */
    public Map<String, String> serviceQueryOrder(WebsitSalesPayOrder order) throws RemoteServiceException {
        Map<String, String> reqMap = new HashMap<>();
        if (StringUtils.isNotBlank(order.getOrgId())) {
            reqMap.put("orgid", order.getOrgId());
        }
        reqMap.put("cusid", order.getMchNo());
        reqMap.put("appid", order.getAppid());
        reqMap.put("reqsn", order.getOutTradeNo());
        reqMap.put("trxid", order.getOrderNo());

        HashMap<String, String> heads = new HashMap();
        String token = commonLogic.getInfToken();
        if (StringUtils.isEmpty(token)) {
            throw new RemoteServiceException("获取接口令牌失败");
        }
        heads.put("authorization_token", token);

        String content = HttpUtils.requestPostBody(commonLogic.getInfUrl() + "/pay/csb/order/query", JSON.toJSONString(reqMap), heads);

        Map<String, Object> resMap = JSON.parseObject(content, new TypeReference<HashMap<String, Object>>() {});

        if (!Optional.ofNullable(resMap.get("message")).orElse("error").toString().equals("success")) {
            log.error("通联交易查询接口执行失败: {}", resMap);
            throw new RemoteServiceException("通联交易查询接口执行失败：" + resMap.get("message"));
        }

        return (Map<String, String>) resMap.get("data");
    }

    /**
     * 通联支付退款
     */
//    public Map<String, String> serviceRefundOrder(SalesPayList paylist, BigDecimal refundValue) throws RemoteServiceException {
//        Map<String, String> reqMap = new HashMap<>();
//        if (StringUtils.isNotBlank(paylist.getMchNo())) {
//            reqMap.put("orgid", paylist.getMchNo());
//        }
//        reqMap.put("appid", paylist.getAppid());
//        reqMap.put("cusid", paylist.getSubMchNo());
//        reqMap.put("trxamt", (int) ArithUtils.mul(refundValue.doubleValue(), 100) + ""); // 退款金额 单位：分
//        reqMap.put("reqsn", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"))); // 商户的退款订单号
//        reqMap.put("oldreqsn", paylist.getOutTradeNo()); // 原交易的商户订单号
//        reqMap.put("oldtrxid", paylist.getOrderNo()); // 原交易的收银宝平台流水
//        reqMap.put("trxid", paylist.getOrderNo());
//
//        HashMap<String, String> heads = new HashMap();
//        String token = commonLogic.getInfToken();
//        if (StringUtils.isEmpty(token)) {
//            throw new RemoteServiceException("获取接口令牌失败");
//        }
//        heads.put("authorization_token", token);
//
//        String content = HttpUtils.requestPostBody(commonLogic.getInfUrl() + "/pay/csb/order/refund", JSON.toJSONString(reqMap), heads);
//
//        Map<String, Object> resMap = JSON.parseObject(content, new TypeReference<HashMap<String, Object>>() {});
//
//        if (!Optional.ofNullable(resMap.get("message")).orElse("error").toString().equals("success")) {
//            log.error("通联交易退款接口执行失败: {}", resMap);
//            throw new RemoteServiceException("通联交易退款接口执行失败：" + resMap.get("message"));
//        }
//
//        return (Map<String, String>) resMap.get("data");
//    }

    /**
     * 通联支付关闭
     */
//    public Map<String, String> serviceCloseOrder(SalesPayList payRecord) throws RemoteServiceException {
//        Map<String, String> reqMap = new HashMap<>();
//        if (StringUtils.isNotBlank(payRecord.getMchNo())) {
//            reqMap.put("orgid", payRecord.getMchNo());
//        }
//        reqMap.put("appid", payRecord.getAppid());
//        reqMap.put("cusid", payRecord.getSubMchNo());
//        reqMap.put("reqsn", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"))); // 商户的退款订单号
//        reqMap.put("oldreqsn", payRecord.getOutTradeNo()); // 原交易的商户订单号
//        reqMap.put("oldtrxid", payRecord.getOrderNo()); // 原交易的收银宝平台流水
//        reqMap.put("trxid", payRecord.getOrderNo());
//
//        HashMap<String, String> heads = new HashMap();
//        String token = commonLogic.getInfToken();
//        if (StringUtils.isEmpty(token)) {
//            throw new RemoteServiceException("获取接口令牌失败");
//        }
//        heads.put("authorization_token", token);
//
//        String content = HttpUtils.requestPostBody(commonLogic.getInfUrl() + "/pay/csb/order/close", JSON.toJSONString(reqMap), heads);
//
//        Map<String, Object> resMap = JSON.parseObject(content, new TypeReference<HashMap<String, Object>>() {});
//
//        String message = Optional.ofNullable(resMap.get("message")).orElse("error").toString();
//        if (message.equals("success") || message.equals("交易已关闭")) {
//            return (Map<String, String>) resMap.get("data");
//        }
//        log.error("通联交易关闭接口执行失败: {}", resMap);
//        throw new RemoteServiceException("通联交易关闭接口执行失败：" + resMap.get("message"));
//    }

    @Transactional
    public void queryAllinpayOrder(WebsitSalesPayOrder order) throws ParseException {
        Map<String, String> resMap = this.serviceQueryOrder(order);
        String fintime = resMap.get("fintime"); // 交易完成时间
        String chnltrxid = resMap.get("chnltrxid"); // 渠道流水号
        String acct = resMap.get("acct"); // 支付平台用户标识
        String trxstatus = resMap.get("trxstatus"); // 交易状态
        String errmsg = resMap.get("errmsg"); // 原因

        switch(trxstatus.trim()) {
            case "0000":
                // 支付成功
                if (order.getOrderId().contains("X") && order.getOrderType().equals(PayOrderTypeEnum.S.getKey())) {
                    websitSalesService.lambdaUpdate()
                            .set(WebsitSales::getPayFlag, IsYesNoEnum.YES.getKey())
                            .set(WebsitSales::getFlag, "PAY_NOT_TAKE")
                            .set(WebsitSales::getPayTime, DateUtils.parseDate2(fintime))
                            .set(WebsitSales::getPayNo, chnltrxid)
                            .set(WebsitSales::getPayType, PayTypeEnum.ALLINPAY.getKey())
                            .eq(WebsitSales::getSalesId, order.getOrderId())
                            .update();
                    websitSalesItemService.lambdaUpdate()
                            .set(WebsitSalesItem::getPayType, PayTypeEnum.ALLINPAY.getKey())
                            .eq(WebsitSalesItem::getSalesId, order.getOrderId())
                            .update();
                } else if (order.getOrderId().contains("PJ") && order.getOrderType().equals(PayOrderTypeEnum.S.getKey())) {
                    try {
                        log.info("执行配件库存处理方法");
                        order.setPayTime(DateUtils.parseDate2(fintime))
                                .setTransactionId(chnltrxid)
                                .setOpenid(acct);
                        websitPartsSalesOrderLogic.handlePaySuccessMethod(order);
                    } catch (RemoteServiceException rse) {
                        websitPartsSalesService.lambdaUpdate()
                                .set(WebsitPartsSales::getPayFlag, PartsPayFlagEnum.PAY_NOT_STOCK.getKey())
                                .set(WebsitPartsSales::getStatus, PartsOrderStatusEnum.EXCEPTION.getKey())
                                .set(WebsitPartsSales::getPayTime, DateUtils.parseDate2(fintime))
                                .set(WebsitPartsSales::getTransactionId, chnltrxid)
                                .set(WebsitPartsSales::getOpenid, acct)
                                .set(WebsitPartsSales::getErr, rse.getMessage())
                                .eq(WebsitPartsSales::getId, order.getOrderId())
                                .update();
                        log.info("配件销售单库存处理异常，更新订单：" + rse.getMessage());
                    } catch (Exception e) {
                        log.info("配件销售单库存处理异常：" + e.getMessage());
                    }
                } else if (order.getOrderId().contains("PC") && order.getOrderType().equals(PayOrderTypeEnum.S.getKey())) {
                    WebsitPartsWorkerCreditRecord record = websitPartsWorkerCreditRecordService.getById(order.getOrderId());
                    record.setCreditStatus(true)
                            .setRecAmountMode(PayTypeEnum.ALLINPAY.getKey())
                            .updateById();
                }

                order.setPayFlag(IsYesNoEnum.YES.getKey())
                        .setPayTime(DateUtils.parseDate2(fintime))
                        .setTransactionId(chnltrxid)
                        .setOpenid(acct)
                        .setLastStatus(trxstatus)
                        .setLastMsg(errmsg)
                        .updateById();
                break;
            case "2000":
                // 交易处理中
                int count = order.getRunCount() + 1;
                order.setRunCount(count)
                        .setRunTime(DateUtil.offsetSecond(DateUtil.date(), count * 5))
                        .setLastStatus(trxstatus)
                        .setLastMsg(errmsg)
                        .updateById();
                break;
            default:
                log.info("未定义交易状态：" + trxstatus);
                order.setRunCount(50)
                        .setLastStatus(trxstatus)
                        .setLastMsg(errmsg)
                        .updateById();
        }
    }
}
