package com.fs.huifuPay.sdk.opps.core.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.StringUtils;
import com.fs.common.utils.spring.SpringUtils;
import com.fs.company.domain.CompanyDivItem;
import com.fs.company.mapper.CompanyDivConfigMapper;
import com.fs.company.param.CompanyAcctInfo;
import com.fs.company.service.ICompanyDivConfigService;
import com.fs.company.service.ICompanyDivItemService;
import com.fs.company.service.impl.CompanyDivConfigServiceImpl;
import com.fs.company.vo.CompanyDivConfigVo;
import com.fs.his.domain.FsPackageOrder;
import com.fs.his.domain.FsPayConfig;
import com.fs.his.domain.FsStoreOrder;
import com.fs.his.domain.FsStorePayment;
import com.fs.his.mapper.FsStorePaymentMapper;
import com.fs.hisStore.domain.FsStorePaymentScrm;
import com.fs.hisStore.mapper.FsStorePaymentScrmMapper;
import com.fs.huifuPay.domain.HuiFuConfirmOrder;
import com.fs.huifuPay.domain.HuiFuCreateOrder;
import com.fs.huifuPay.domain.HuiFuQueryOrderResult;
import com.fs.huifuPay.service.HuiFuService;
import com.fs.system.domain.SysConfig;
import com.fs.system.mapper.SysConfigMapper;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@Slf4j
public class HuiFuUtils {
    private static ICompanyDivConfigService companyDivConfigService = SpringUtils.getBean(ICompanyDivConfigService.class);
    private static ICompanyDivItemService companyDivItemService = SpringUtils.getBean(ICompanyDivItemService.class);
    private static FsStorePaymentMapper fsStorePaymentMapper = SpringUtils.getBean(FsStorePaymentMapper.class);
    private static FsStorePaymentScrmMapper fsStorePaymentScrmMapper = SpringUtils.getBean(FsStorePaymentScrmMapper.class);
    private static HuiFuService huiFuService = SpringUtils.getBean(HuiFuService.class);

    /**
     * 处理分账
     *
     * @param huiFuCreateOrder
     * @param companyId
     */
    public static void doDiv(HuiFuCreateOrder huiFuCreateOrder, Long companyId) throws Exception {
        //默认汇付账户
        SysConfigMapper sysConfigMapper = SpringUtils.getBean(SysConfigMapper.class);
        SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.pay");
        FsPayConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), FsPayConfig.class);
        String defaultHuifuId = fsPayConfig.getHuifuId();
        //查询是否开启分账
        if (companyId != null) {

            CompanyDivConfigVo configVo = companyDivConfigService.selectCompanyDivConfigByCompanyId(companyId);
            if (configVo != null) {
                Integer divFlag = configVo.getDivFlag();
                if (divFlag != null && divFlag == 1) {
                    //开启分账
                    //汇付传参
                    Map<String, Object> acctSplitBunchMap = new HashMap<>();
                    List<Map<String, Object>> acctInfos = new ArrayList();
                    List<CompanyAcctInfo> acctInfoVos = configVo.getAcctInfos();
                    if (acctInfoVos != null && !acctInfoVos.isEmpty()) {
                        String delayAcctFlag = configVo.getDelayAcctFlag();
                        String percentageFlag = configVo.getPercentageFlag();
                        if (StringUtils.isNotBlank(delayAcctFlag) && delayAcctFlag.equals("N")) {
                            //实时分账
                            huiFuCreateOrder.setDelayAcctFlag("N");
                            extractedDiv(huiFuCreateOrder, percentageFlag, acctSplitBunchMap, acctInfoVos, acctInfos, defaultHuifuId, configVo);
                        } else if (StringUtils.isNotBlank(delayAcctFlag) && delayAcctFlag.equals("Y")) {
                            //延时分账 确认交易时传参
                            huiFuCreateOrder.setDelayAcctFlag("Y");
                            extractedDiv(huiFuCreateOrder, percentageFlag, acctSplitBunchMap, acctInfoVos, acctInfos, defaultHuifuId, configVo);
                        }

                    }
                }
            }
        }
    }

    private static void extractedDiv(HuiFuCreateOrder huiFuCreateOrder, String percentageFlag,
                                     Map<String, Object> acctSplitBunchMap, List<CompanyAcctInfo> acctInfoVos,
                                     List<Map<String, Object>> acctInfos, String defaultHuifuId, CompanyDivConfigVo configVo) {
        if (StringUtils.isNotBlank(percentageFlag) && percentageFlag.equals("Y")) {
            acctSplitBunchMap.put("percentage_flag", "Y");
            Float total = 0f;
            //百分比分账
            for (CompanyAcctInfo acctInfo : acctInfoVos) {
                Map<String, Object> map = new HashMap<>();
                Float percentageDiv = acctInfo.getPercentageDiv();
                if (percentageDiv == null || percentageDiv <= 0) {
                    continue;
                }
                map.put("percentage_div", String.format("%.2f", percentageDiv));
                if (percentageDiv > 100) {
                    acctInfos = null;
                    break;
                }
                total = total + percentageDiv;
                if (total > 100) {
                    acctInfos = null;
                    break;
                }
                if (StringUtils.isBlank(acctInfo.getAcctId())) {
                    acctInfo.setAcctId(null);
                }
                map.put("huifu_id", acctInfo.getHuifuId());
                acctInfos.add(map);
            }
            if (acctInfos != null && !acctInfos.isEmpty()) {
                Map<String, Object> defaultAccount = new HashMap<>();
                defaultAccount.put("percentage_div", String.format("%.2f", 100f - total));
                defaultAccount.put("huifu_id", defaultHuifuId);
                acctInfos.add(defaultAccount);
            }


        } else {
            acctSplitBunchMap.put("percentage_flag", "N");
            // 固定金额
            BigDecimal amtTotal = BigDecimal.ZERO;
            //支付金额
            BigDecimal initTotal = new BigDecimal(huiFuCreateOrder.getTransAmt()).setScale(2, RoundingMode.FLOOR);
            for (CompanyAcctInfo acctInfo : acctInfoVos) {
                Map<String, Object> map = new HashMap<>();
                BigDecimal divAmt = acctInfo.getDivAmt().setScale(2, RoundingMode.FLOOR);
                if (divAmt.compareTo(BigDecimal.ZERO) <= 0) {
                    continue;
                }
                map.put("div_amt", divAmt.toString());
                amtTotal = amtTotal.add(divAmt);
                if (amtTotal.compareTo(initTotal) > 0) {
                    acctInfos = null;
                    break;
                }
                if (StringUtils.isBlank(acctInfo.getAcctId())) {
                    acctInfo.setAcctId(null);
                }
                map.put("huifu_id", acctInfo.getHuifuId());
                acctInfos.add(map);
            }
            if (acctInfos != null && !acctInfos.isEmpty()) {
                if (initTotal.compareTo(amtTotal) < 0) {
                    acctInfos = null;
                } else {
                    Map<String, Object> defaultAccount = new HashMap<>();
                    defaultAccount.put("div_amt", String.valueOf(initTotal.subtract(amtTotal).setScale(2, RoundingMode.FLOOR)));
                    defaultAccount.put("huifu_id", defaultHuifuId);
                    acctInfos.add(defaultAccount);
                }
            }

        }

        if (acctInfos != null) {
            acctSplitBunchMap.put("is_clean_split", configVo.getIsCleanSplit());
            acctSplitBunchMap.put("acct_infos", acctInfos);
            huiFuCreateOrder.setAcctSplitBunch(JSON.toJSONString(acctSplitBunchMap));
        }
    }

    public static void saveDivItem(HuiFuCreateOrder o, String orderCode, String payCode) {
        CompanyDivItem companyDivItem = new CompanyDivItem();
        if (StringUtils.isNotBlank(o.getAcctSplitBunch())) {
            companyDivItem.setOrderCode(orderCode);
            companyDivItem.setPayCode(payCode);
            companyDivItem.setDetail(o.getAcctSplitBunch());
            companyDivItem.setIsRefund(0); //支付
            if (StringUtils.isNotBlank(o.getDelayAcctFlag()) && o.getDelayAcctFlag().equals("Y")) {
                companyDivItem.setIsDelay(1); //延迟分账

            } else {
                companyDivItem.setIsDelay(0);
                companyDivItem.setDelayStatus(0);
            }
            companyDivItemService.insertCompanyDivItem(companyDivItem);
        }
    }

    /**
     * 回调修改分账明细状态
     *
     * @param payCode
     */
    public static void updateDivItem(String payCode) {
        //修改分账状态
        CompanyDivItem companyDivItem = companyDivItemService.selectCompanyDivItemByPayCode(payCode);
        if (companyDivItem != null) {
            companyDivItem.setIsPay(1);
            companyDivItemService.updateCompanyDivItem(companyDivItem);
            try {
                //查询是否分账payment
                FsStorePayment fsStorePayment = fsStorePaymentMapper.selectFsStorePaymentByPaymentCode(payCode);
                if (fsStorePayment == null) {
                    FsStorePaymentScrm fsStorePaymentScrm = fsStorePaymentScrmMapper.selectFsStorePaymentByPaymentCode(payCode);
                    if (fsStorePaymentScrm != null) {
                        fsStorePaymentScrm.setShareStatus(1);
                        fsStorePaymentScrm.setShareMoney(fsStorePaymentScrm.getPayMoney());
                        fsStorePaymentScrmMapper.updateFsStorePayment(fsStorePaymentScrm);
                    }
                } else {
                    fsStorePayment.setShareStatus(1);
                    fsStorePayment.setShareMoney(fsStorePayment.getPayMoney());
                    fsStorePaymentMapper.updateFsStorePayment(fsStorePayment);
                }
            } catch (Exception e) {
                log.error("更新payment表分账状态失败{}", e.getMessage());
            }
        }
    }


    /**
     * 处理分账退款
     *
     * @param reMoney
     * @param payment
     * @param extendInfoMap
     */
    public static CompanyDivItem doRefundDiv(BigDecimal payPrice, BigDecimal reMoney, FsStorePayment payment, Map<String, Object> extendInfoMap) {
        CompanyDivItem companyDivItem = null;
        companyDivItem = companyDivItemService.selectCompanyDivItemByPayCode(payment.getPayCode());
        if (companyDivItem != null) {
            if (payPrice.compareTo(reMoney) > 0) {
                //部分退款
                if (companyDivItem != null) {
                    SysConfigMapper sysConfigMapper = SpringUtils.getBean(SysConfigMapper.class);
                    SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.pay");
                    FsPayConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), FsPayConfig.class);
                    String defaultHuiFuId = fsPayConfig.getHuifuId(); //默认汇付id

                    String detail = companyDivItem.getDetail();
                    if (StringUtils.isNotBlank(detail)) {
                        JSONObject acctSplitBunch = JSONObject.parseObject(detail);
                        if (acctSplitBunch.get("percentage_flag") != null) {
                            List<Map<String, Object>> param = new ArrayList(); //传入汇付参数

                            String percentageFlag = acctSplitBunch.get("percentage_flag").toString();
                            Object acctInfosObj = acctSplitBunch.get("acct_infos");
                            if (acctInfosObj != null) {
                                if ("Y".equals(percentageFlag)) {
                                    // 百分比分账
                                    List<Map> acctInfos = JSON.parseArray(acctInfosObj.toString(), Map.class);
                                    if (acctInfos != null && !acctInfos.isEmpty()) {
                                        BigDecimal remainMoney = reMoney;

                                        for (Map acctInfo : acctInfos) {
                                            String percentageDiv = acctInfo.get("percentage_div").toString();
                                            BigDecimal divAmt = reMoney.multiply(BigDecimal.valueOf(Float.valueOf(percentageDiv)).multiply(BigDecimal.valueOf(0.01))).setScale(2, BigDecimal.ROUND_HALF_UP);
                                            if (divAmt.compareTo(BigDecimal.ZERO) <= 0) {
                                                continue;
                                            }
                                            remainMoney = remainMoney.subtract(divAmt);
                                            String huiFuId = acctInfo.get("huifu_id").toString();
                                            Map<String, Object> map = new HashMap<>();
                                            map.put("div_amt", divAmt);
                                            map.put("huifu_id", huiFuId);
//                                                part_loan_amt	垫资金额
                                            param.add(map);
                                            if (remainMoney.compareTo(BigDecimal.ZERO) >= 0) {
                                                break;
                                            }
                                        }
                                        if (remainMoney.compareTo(BigDecimal.ZERO) >= 0) {
                                            BigDecimal divAmt = reMoney.subtract(remainMoney).setScale(2, BigDecimal.ROUND_HALF_UP);
                                            Map<String, Object> map = new HashMap<>();
                                            map.put("div_amt", divAmt);
                                            map.put("huifu_id", defaultHuiFuId);
                                            param.add(map);
                                        }
                                    }

                                } else if ("N".equals(percentageFlag)) {
                                    // 金额分账 目前按照排序从第一个开始扣 扣到满足退款金额
                                }
                                if (!param.isEmpty()) {
                                    extendInfoMap.put("acct_split_bunch", JSON.toJSONString(param));
                                }
                            }

                        }


                    }
                }
            }
        }
        return companyDivItem;

    }

    public static void confirmByOrderCode(String orderCode) {
        FsStorePayment queryParam = new FsStorePayment();
        queryParam.setBusinessCode(orderCode);
        queryParam.setStatus(1);
        List<FsStorePayment> fsStorePayments = fsStorePaymentMapper.selectFsStorePaymentList(queryParam);
        if (!fsStorePayments.isEmpty()) {
            FsStorePayment fsStorePayment = fsStorePayments.get(0);
            Integer businessType = fsStorePayment.getBusinessType();
            String appId = fsStorePayment.getAppId();
            Date payTime = fsStorePayment.getPayTime();
            String payCode = fsStorePayment.getPayCode();
            confirm(payCode, businessType, appId, payTime);
        }
    }

    public static void confirmByPayCode(String payCode) {
        FsStorePayment fsStorePayment = fsStorePaymentMapper.selectFsStorePaymentByPaymentCode(payCode);
        if (fsStorePayment == null){
            confirmByPayCodeScrm(payCode);
        } else {
            Integer businessType = fsStorePayment.getBusinessType();
            String appId = fsStorePayment.getAppId();
            Date payTime = fsStorePayment.getPayTime();
            confirm(payCode, businessType, appId, payTime);
        }
    }

    public static void confirmByOrderCodeScrm(String orderCode) {
        FsStorePaymentScrm queryParam = new FsStorePaymentScrm();
        queryParam.setBusinessCode(orderCode);
        queryParam.setStatus(1);
        List<FsStorePaymentScrm> fsStorePayments = fsStorePaymentScrmMapper.selectFsStorePaymentList(queryParam);
        if (!fsStorePayments.isEmpty()) {
            FsStorePaymentScrm fsStorePayment = fsStorePayments.get(0);
            Integer businessType = fsStorePayment.getBusinessType();
            String appId = fsStorePayment.getAppId();
            Date payTime = fsStorePayment.getPayTime();
            String payCode = fsStorePayment.getPayCode();
            confirm(payCode, businessType, appId, payTime);
        }
    }

    public static void confirmByPayCodeScrm(String payCode) {
        FsStorePaymentScrm fsStorePayment = fsStorePaymentScrmMapper.selectFsStorePaymentByPaymentCode(payCode);
        if (fsStorePayment != null) {
            Integer businessType = fsStorePayment.getBusinessType();
            String appId = fsStorePayment.getAppId();
            Date payTime = fsStorePayment.getPayTime();
            confirm(payCode, businessType, appId, payTime);
        }
    }

    private static void confirm(String payCode, Integer businessType, String appId,Date payTime) {
        CompanyDivItem companyDivItem = companyDivItemService.selectCompanyDivItemByPayCode(payCode);
        if (companyDivItem != null) {
            if (companyDivItem.getIsDelay() != null && companyDivItem.getIsDelay() == 1) {
                //延时分账 确认订单分账
                HuiFuConfirmOrder confirmOrder = new HuiFuConfirmOrder();
                String orgReqSeqId = payCode;
                switch (businessType) {
                    case 1:
                        orgReqSeqId = "inquiry-" + orgReqSeqId;
                        break;
                    case 2:
                        orgReqSeqId = "store-" + orgReqSeqId;
                        break;
                    case 3:
                        orgReqSeqId = "package-" + orgReqSeqId;
                        break;
                    case 4:
                        orgReqSeqId = "course-" + orgReqSeqId;
                        break;
                    case 5:
                        orgReqSeqId = "appvip-" + orgReqSeqId;
                        break;
                    case 6:
                        orgReqSeqId = "integral-" + orgReqSeqId;
                        break;
                    case 7:
                        orgReqSeqId = "payment-" + orgReqSeqId;
                        break;
                }
                confirmOrder.setOrgReqSeqId(orgReqSeqId);
                if (payTime == null) {
                    return;
                }
                confirmOrder.setOrgReqDate(DateUtils.parseDateToStr("yyyyMMdd", payTime));
                confirmOrder.setAppId(appId);
                HuiFuQueryOrderResult huiFuResult = huiFuService.delayTransConfirm(confirmOrder);
                /**
                 * {
                 * 	"org_req_date": "20251111",
                 * 	"resp_desc": "交易成功",
                 * 	"trans_stat": "S",
                 * 	"org_hf_seq_id": "002900TOP2A251111092843P250ac139c1400000",
                 * 	"confirmed_amt": "0.02",
                 * 	"hf_seq_id": "003500TOP3A251111101202P443ac13696f00000",
                 * 	"org_mer_ord_id": "package-1988056235747835904",
                 * 	"org_req_seq_id": "package-1988056235747835904",
                 * 	"unconfirm_amt": "0.00",
                 * 	"req_seq_id": "202511111011597366vxgcpozqvirxg",
                 * 	"req_date": "20251111",
                 * 	"resp_code": "00000000",
                 * 	"acct_resp_desc": "成功",
                 * 	"huifu_id": "6666000171179317",
                 * 	"acct_split_bunch": "{\"acct_infos\":[{\"acct_id\":\"F13245119\",\"div_amt\":\"0.01\",\"huifu_id\":\"6666000181121137\",\"split_fee_acct_id\":\"F13245119\",\"split_fee_amt\":\"0.00\",\"split_fee_huifu_id\":\"6666000181121137\"},{\"acct_id\":\"F08847757\",\"div_amt\":\"0.01\",\"huifu_id\":\"6666000171179317\"}]}",
                 * 	"acct_resp_code": "000"
                 * }
                 */
                if (huiFuResult != null) {
                    if ("00000000".equals(huiFuResult.getResp_code())) {
                        companyDivItem.setDelayStatus(1);
                        companyDivItemService.updateCompanyDivItem(companyDivItem);
                    }
                }
            }
        }
    }
}
