package com.hzs.third.pay.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.hzs.common.core.config.BdConfig;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.EDataSource;
import com.hzs.common.core.enums.EEnv;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.domain.third.pay.TOnlinePayment;
import com.hzs.common.domain.third.pay.TOnlinePaymentSepAcc;
import com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD;
import com.hzs.common.security.utils.SecurityUtils;
import com.hzs.third.pay.config.JdPayBankProperties;
import com.hzs.third.pay.config.JdPayConfig;
import com.hzs.third.pay.config.JdPaySeparateAccountConfig;
import com.hzs.third.pay.config.JdPayWechatAlipayProperties;
import com.hzs.third.pay.jdpay.dto.JdPayAggregateCreateOrderRequest;
import com.hzs.third.pay.jdpay.dto.JdPayAggregateCreateOrderResponse;
import com.hzs.third.pay.jdpay.dto.JdPayDivisionAccount;
import com.hzs.third.pay.jdpay.dto.JdPayDivisionAccountTradeInfo;
import com.hzs.third.pay.jdpay.sdk.JdPay;
import com.hzs.third.pay.jdpay.util.GsonUtil;
import com.hzs.third.pay.service.IJdPayService;
import com.hzs.third.pay.service.ITOnlineCardService;
import com.hzs.third.pay.service.ITOnlinePaymentSepAccService;
import com.hzs.third.pay.service.ITOnlinePaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * 京东支付服务
 */
@Slf4j
@Service
public class JdPayServiceImpl implements IJdPayService {

    @Autowired
    private JdPayConfig jdPayConfig;
    @Autowired
    private ITOnlineCardService itOnlineCardService;
    @Resource(name = "jdPayBank")
    private JdPay jdPay;
    @Autowired
    private JdPayBankProperties jdPayBankProperties;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ITOnlinePaymentSepAccService itOnlinePaymentSepAccService;

    @Autowired
    private ITOnlinePaymentService itOnlinePaymentService;

    @Resource
    private JdPayWechatAlipayProperties jdPayWechatAlipayProperties;

    @Override
    public R<String> cashRegister(TOnlinePayment onlinePayment, EDataSource dataSource) {
        try {
            // 交易场景（ONLINE_APP：线上移动端  ONLINE_PC:线上PC）
            String sceneType = "ONLINE_APP";
            // 交易类型（AGGRE：聚合收银台  AGGRE_QR：PC扫码）
            String tradeType = "AGGRE";
            if (null != dataSource && EDataSource.PC.getValue().equals(dataSource.getValue())) {
                sceneType = "ONLINE_PC";
                tradeType = "AGGRE_QR";
            }

//            String userId = onlinePayment.getPkCreator().toString();
            String userId = SecurityUtils.getMemberCode();
            if (EEnv.TEST.getValue().equals(BdConfig.getEnv())) {
                userId = "T_" + userId;
            }

            JdPayAggregateCreateOrderRequest request = JdPayAggregateCreateOrderRequest.builder()
                    // 商户订单号（最大32位）
                    .outTradeNo(onlinePayment.getBusinessCode())
                    // 订单总金额（单位：分）
                    .tradeAmount(onlinePayment.getPayMoney().multiply(new BigDecimal("100")).intValue() + "")
                    // 订单创建时间（最大14位：yyyyMMddHHmmss）
                    .createDate(DateUtils.parseDateToFormat(DateUtils.YAMMERERS, onlinePayment.getCreationTime()))
                    // 订单有效时长（分钟）
                    .tradeExpiryTime("1440")
                    // 交易名称
                    .tradeSubject("支付：" + onlinePayment.getBusinessCode())
                    // 交易描述
                    .tradeRemark("支付：" + onlinePayment.getBusinessCode())
                    // 币种
                    .currency("CNY")
                    // 用户IP
                    .userIp(InetAddress.getLocalHost().getHostAddress())
                    // 通道业务类型
                    .bizTp("100001")
                    // 回传字段
                    .returnParams(onlinePayment.getBusinessType().toString())
                    // 用户标识（收银台必传）
                    .userId(userId)
                    // 同步通知URL（收银台必传，页面回调地址）
                    .pageBackUrl(jdPayBankProperties.getPageBackUrl() + "?extParam=" + onlinePayment.getExtParam())
                    .callbackUrl(jdPayBankProperties.getPageBackUrl() + "?extParam=" + onlinePayment.getExtParam())
                    // 支付回调地址
                    .notifyUrl(jdPayBankProperties.getNotifyUrl())
                    // 交易类型
                    .tradeType(tradeType)
                    // 交易场景（ONLINE_APP：线上移动端  ONLINE_PC:线上PC）
                    .sceneType(sceneType)
                    .accessType("MINIAPP")
                    .build();


            JdPayDivisionAccount divisionAccount = new JdPayDivisionAccount();
            List<JdPayDivisionAccountTradeInfo> divisionAccountTradeInfoList = new ArrayList<JdPayDivisionAccountTradeInfo>();
            List<TOnlinePaymentSepAccD> sepAccDList = new ArrayList<>();
            if(ObjectUtil.isNotEmpty(jdPayBankProperties)){
                List<JdPaySeparateAccountConfig> separateAccounts = jdPayBankProperties.getSeparateAccounts();
                separateAccounts.sort(Comparator.comparing(JdPaySeparateAccountConfig::getProportion).reversed());
                if(ObjectUtil.isNotEmpty(separateAccounts)){
                    BigDecimal tradeAmount = onlinePayment.getPayMoney();
                    BigDecimal remaining = onlinePayment.getPayMoney();
                    for (int i = 0; i < separateAccounts.size(); i++) {
                        JdPaySeparateAccountConfig separateAccount = separateAccounts.get(i);
                        BigDecimal subTradeAmount;
                        if(i == separateAccounts.size() - 1){
                            subTradeAmount = remaining;
                            log.info("分账 最后一个账户( 总 - 已分账 ) : {}, {}", subTradeAmount, remaining);
                            onlinePayment.setSubAccountMoney(subTradeAmount);
                        }else{
                            subTradeAmount = tradeAmount.multiply(separateAccount.getProportion().setScale(2, BigDecimal.ROUND_DOWN)).setScale(2, BigDecimal.ROUND_DOWN);
                            remaining = remaining.subtract(subTradeAmount).setScale(2, BigDecimal.ROUND_DOWN);
                            onlinePayment.setMainAccountMoney(subTradeAmount);
                            log.info("分账 过程 : {}, {}, {}", subTradeAmount, remaining, separateAccount.getProportion().setScale(2, BigDecimal.ROUND_DOWN));
                        }
                        JdPayDivisionAccountTradeInfo divisionAccountTradeInfo = new JdPayDivisionAccountTradeInfo();
                        divisionAccountTradeInfo.setMerchantNo(separateAccount.getAccount());
                        divisionAccountTradeInfo.setOutTradeNo(onlinePayment.getBusinessCode() + "_" + (i + 1));
                        divisionAccountTradeInfo.setTradeAmount(subTradeAmount.multiply(new BigDecimal(100)).intValue() + "");
                        divisionAccountTradeInfoList.add(divisionAccountTradeInfo);
                        sepAccDList.add(
                                TOnlinePaymentSepAccD.builder()
                                        .account(separateAccount.getAccount())
                                        .proportion(separateAccount.getProportion())
                                        .tradeAmount(subTradeAmount)
                                        .outTradeNo(divisionAccountTradeInfo.getOutTradeNo())
                                        .build()
                        );
                    }
                }
            }

            divisionAccount.setVersion( "V2" );
            divisionAccount.setDivisionAccountTradeInfoList(divisionAccountTradeInfoList);
            request.setDivisionAccount(GsonUtil.toJson(divisionAccount));

            // 请求京东支付接口
            JdPayAggregateCreateOrderResponse response = jdPay.aggregateCreateOrder(request);
            TOnlinePaymentSepAcc sepAcc = TOnlinePaymentSepAcc.builder()
                    .sepAccDList(sepAccDList)
                    .reqContent(request.getDivisionAccount())
                    .reqContentSepAcc(JSONUtil.toJsonStr(divisionAccountTradeInfoList))
                    .version(divisionAccount.getVersion())
                    .respContent(JSONUtil.toJsonStr(response))
                    .tradeAmount(onlinePayment.getPayMoney())
                    .outTradeNo(request.getOutTradeNo())
                    .build();
            if ("00000".equals(response.getResultCode())) {
                // 请求响应成功
                // 京东唯一订单号
                onlinePayment.setPayNumber(response.getTradeNo());
                // 将controller内入库逻辑移至此为止
                onlinePayment.setPayMoney(null);
                itOnlinePaymentService.saveOrUpdate(onlinePayment);
                // 2025年7月1日 保存分账主表&子表
                sepAcc.setPkPayment(onlinePayment.getPkId());
                itOnlinePaymentSepAccService.saveOrUpdateReq(sepAcc);
                if ("AGGRE_QR".equals(tradeType)) {
                    return R.ok(response.getQrCode());
                }
                return R.ok(response.getWebUrl());
            } else {
                log.error("京东收银台返回失败，resultDesc: {}", response.getResultDesc());
                return R.fail("调用京东收银台返回失败");
            }
        } catch (Exception e) {
            log.error("京东收银台处理异常!", e);
            return R.fail("京东收银台处理异常");
        }
    }


}
