package com.jeequan.jeepay.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.applyment.ApplymentBasicInfo;
import com.jeequan.jeepay.core.model.applyment.YspayApplymentInfo;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.service.mapper.SettleInfoMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2023-12-06
 */
@Service
public class SettleInfoService extends ServiceImpl<SettleInfoMapper, SettleInfo>{

    @Autowired private MchApplymentService mchApplymentService;

    @Autowired private MchAppService mchAppService;

    @Autowired private IsvInfoService isvInfoService;

    @Autowired private PayInterfaceDefineService payInterfaceDefineService;

    @Autowired private AgentInfoService agentInfoService;

    @Autowired private MchInfoService mchInfoService;


    /**
     * 分页查询
     * @param iPage
     * @param wrapper
     * @param info
     * @param paramJSON
     * @return
     */
    public Page<SettleInfo> pageList(Page<SettleInfo> iPage, LambdaQueryWrapper<SettleInfo> wrapper, SettleInfo info, JSONObject paramJSON) {
        // 时间范围条件
        Date[] dateRange = info.buildQueryDateRange();
        if (dateRange[0] != null) {
            wrapper.ge(SettleInfo::getUpdatedAt, dateRange[0]);
        }
        if (dateRange[1] != null) {
            wrapper.le(SettleInfo::getUpdatedAt, dateRange[1]);
        }
        wrapper.eq(StringUtils.isNotEmpty(info.getSettleNo()),SettleInfo::getSettleType,info.getSettleType());
        wrapper.eq(StringUtils.isNotEmpty(info.getAccountName()),SettleInfo::getAccountName,info.getAccountName());
        wrapper.eq(StringUtils.isNotEmpty(info.getAccountNo()),SettleInfo::getAccountNo,info.getAccountNo());
        wrapper.eq(info.getState() != null,SettleInfo::getState,info.getState());
        //结算姓名卡号二合一检索
        // TODO: 2024/3/8 涉及加密暂时无法使用
        if (StringUtils.isNotEmpty(info.getNameAndNo())){
            wrapper.and(i -> {
                i.like(SettleInfo::getAccountName, SysConfigService.DB_ENCRYPT_SM4.encryptBase64(info.getNameAndNo()))
                        .or().like(SettleInfo::getAccountNo, SysConfigService.DB_ENCRYPT_SM4.encryptBase64(info.getNameAndNo()));
            });
        }
        //支付通道改为模糊检索
        if (StringUtils.isNotEmpty(info.getIfCode())){
            List<PayInterfaceDefine> interfaceDefineList = payInterfaceDefineService.list(PayInterfaceDefine.gw().like(PayInterfaceDefine::getIfName, info.getIfCode()));
            List<String> collect = interfaceDefineList.stream().map(PayInterfaceDefine::getIfCode).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(collect)){
                wrapper.in(SettleInfo::getIfCode,collect);
            }else {
                wrapper.eq(SettleInfo::getIfCode,info.getIfCode());
            }
        }
        //商户名称商户号二合一检索
        if (StringUtils.isNotEmpty(info.getMchExtNo())){
            wrapper.and(i->{
                i.eq(SettleInfo::getMchExtNo,info.getMchExtNo()).or()
                        .like(SettleInfo::getMchName,info.getMchExtNo());
            });
        }
        //服务商名称服务商号二合一检索
        if (StringUtils.isNotEmpty(info.getAgentName())){
            List<AgentInfo> agentInfos = agentInfoService.list(AgentInfo.gw().like(AgentInfo::getAgentName, info.getAgentName()));
            List<String> collect = agentInfos.stream().map(AgentInfo::getAgentNo).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(collect)){
                wrapper.in(SettleInfo::getAgentNo,collect);
            }else {
                wrapper.eq(SettleInfo::getAgentNo,info.getAgentName());
            }
        }
        //用户名称、用户号、用户手机号三合一
        if (StringUtils.isNotEmpty(info.getMchUserName())){
            List<MchInfo> mchInfoList = mchInfoService.list(MchInfo.gw().eq(MchInfo::getContactTel, info.getMchUserName())
                    .or().like(MchInfo::getMchName, info.getMchUserName()));
            List<String> collect = mchInfoList.stream().map(MchInfo::getMchNo).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(collect)){
                wrapper.in(SettleInfo::getMchNo,collect);
            }else {
                wrapper.eq(SettleInfo::getMchNo,info.getMchUserName());
            }
        }
        //应用名称和id检索二合一
        if (StringUtils.isNotEmpty(info.getAppid())){
            //传入值作为应用名称进行匹配如果匹配不上则为应用id
            List<MchAppEntity> mchAppEntityList = mchAppService.list(MchAppEntity.gw().like(MchAppEntity::getAppName, info.getAppid()));
            List<String> collect = mchAppEntityList.stream().map(MchAppEntity::getAppId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(collect)){
                wrapper.in(SettleInfo::getAppid,collect);
            }else {
                wrapper.eq(SettleInfo::getAppid,info.getAppid());
            }
        }
        //渠道名称、渠道号二合一检索
        if (StringUtils.isNotEmpty(info.getIsvNo())){
            List<IsvInfoEntity> isvInfoEntities = isvInfoService.list(IsvInfoEntity.gw()
                    .like(IsvInfoEntity::getIsvName, info.getIsvNo()).or()
                    .like(IsvInfoEntity::getIsvShortName, info.getIsvNo()));
            List<String> collect = isvInfoEntities.stream().map(IsvInfoEntity::getIsvNo).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(collect)){
                wrapper.in(SettleInfo::getIsvNo,collect);
            }else {
                wrapper.eq(SettleInfo::getIsvNo,info.getIsvNo());
            }
        }

        wrapper.orderByDesc(SettleInfo::getUpdatedAt);
        Page<SettleInfo> page = page(iPage, wrapper);
        //添加返回数据
        if (!page.getRecords().isEmpty()){
            for (SettleInfo record : page.getRecords()) {
                //所属渠道
                if (StringUtils.isNotEmpty(record.getIsvNo())){
                    IsvInfoEntity infoEntity = isvInfoService.getById(record.getIsvNo());
                    if (infoEntity != null){
                        record.setIsvName(infoEntity.getIsvName());
                        record.setIsvShortName(infoEntity.getIsvShortName());
                    }
                }
                //应用名称
                if (StringUtils.isNotEmpty(record.getAppid())){
                    MchAppEntity mchAppEntity = mchAppService.getById(record.getAppid());
                    if (mchAppEntity != null){
                        record.setAppName(mchAppEntity.getAppName());
                    }
                }
                //返回服务商信息
                if (StringUtils.isNotEmpty(record.getAgentNo())){
                    AgentInfo agentInfo = agentInfoService.getById(record.getAgentNo());
                    if (agentInfo != null){
                        record.setAgentName(agentInfo.getAgentName());
                        record.setAgentContactTel(DesensitizedUtil.mobilePhone(agentInfo.getContactTel()));
                    }
                }
                //返回用户信息
                if (StringUtils.isNotEmpty(record.getMchNo())){
                    MchInfo byId = mchInfoService.getById(record.getMchNo());
                    if (byId != null){
                        record.setMchUserName(byId.getMchName());
                        record.setMchUserPhone(DesensitizedUtil.mobilePhone(byId.getContactTel()));
                    }
                }
            }
        }
        return page;
    }

    /**
     * 初始化D0的结算数据
     * @param payOrder
     */
    public void initD0Settle(PayOrder payOrder) {
        //TODO 判断是否是D0的订单 如果是则生成一条待结算记录
        if(CS.SETTLEMENT_TYPE.D0.equals(payOrder.getSettleType())){
            //计算退款金额
            SettleInfo settleInfo = new SettleInfo(payOrder,0L,payOrder.getCreatedAt(),payOrder.getCreatedAt());
            MchApplyment applyment = mchApplymentService.getById(payOrder.getMchExtNo());
            ApplymentBasicInfo parse = JSON.parseObject(applyment.getApplyDetailInfo(), ApplymentBasicInfo.class);
            String cardNo = parse.getSettAccountNo();
            String cardName = parse.bankAccountName();
            String bankName = parse.getSettAccountBankName();
            settleInfo.setAccountNo(cardNo);
            settleInfo.setAccountName(cardName);
            settleInfo.setBankName(bankName);
            save(settleInfo);
        }
    }

    public ApiRes getCount(List<SettleInfo> infoList){
        HashMap<String, Object> resutMap = new HashMap<>();
        if (CollUtil.isNotEmpty(infoList)){
            //成功交易
            //List<SettleInfo> successList = infoList.stream().filter(p -> p.getState() == 2).collect(Collectors.toList());

            BigDecimal succesAmount=BigDecimal.ZERO;
            int successAll=0;
            for (SettleInfo settleInfo : infoList) {
                succesAmount=succesAmount.add(BigDecimal.valueOf(settleInfo.getTransactionAmount()));
                successAll += settleInfo.getTransactionNumber();
            }
            //成功交易金额
            resutMap.put("successAmount",succesAmount);
            //成功交易笔数
            resutMap.put("successAll",successAll);


            //手续费
            List<SettleInfo> feeList = infoList.stream().filter(f -> f.getFee() != 0).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(feeList)){
                BigDecimal feeAmount=BigDecimal.ZERO;
                for (SettleInfo settleInfo : feeList) {
                    feeAmount=feeAmount.add(BigDecimal.valueOf(settleInfo.getFee()));
                }
                //交易手续费
                resutMap.put("feeAmount",feeAmount);
                //交易手续费笔数
                resutMap.put("feeAll",feeList.size());
            }else {
                resutMap.put("feeAmount",0);
                resutMap.put("feeAll",0);
            }

            //垫资费
            List<SettleInfo> CashFeeList = infoList.stream().filter(f -> f.getCashFee() != 0).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(CashFeeList)){
                BigDecimal CashFeeAmount=BigDecimal.ZERO;
                for (SettleInfo settleInfo : CashFeeList) {
                    CashFeeAmount=CashFeeAmount.add(BigDecimal.valueOf(settleInfo.getCashFee()));
                }
                //垫资费
                resutMap.put("cashFeeAmount",CashFeeAmount);
                //垫资费笔数
                resutMap.put("cashFeeAll",CashFeeList.size());
            }else {
                resutMap.put("cashFeeAmount",0);
                resutMap.put("cashFeeAll",0);
            }

            //结算金额
            BigDecimal allAmount=BigDecimal.ZERO;
            for (SettleInfo settleInfo : infoList) {
                allAmount=allAmount.add(BigDecimal.valueOf(settleInfo.getSettleAmt()));
            }
            //结算总金额
            resutMap.put("allAmount",allAmount);
            //结算总笔数
            resutMap.put("allSettle",infoList.size());

            //待结算金额
            List<SettleInfo> waitList = infoList.stream().filter(p -> p.getState() != 2 && p.getState() != -1).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(waitList)){
                BigDecimal waitAmount=BigDecimal.ZERO;
                for (SettleInfo settleInfo : waitList) {
                    waitAmount=waitAmount.add(BigDecimal.valueOf(settleInfo.getSettleAmt()));
                }
                //成功交易金额
                resutMap.put("waitAmount",waitAmount);
                //成功交易笔数
                resutMap.put("waitAll",waitList.size());
            }else {
                resutMap.put("waitAmount",0);
                resutMap.put("waitAll",0);
            }

        }else {
            resutMap.put("successAmount",0);
            resutMap.put("successAll",0);
            resutMap.put("feeAmount",0);
            resutMap.put("feeAll",0);
            resutMap.put("cashFeeAmount",0);
            resutMap.put("cashFeeAll",0);
            resutMap.put("allAmount",0);
            resutMap.put("allSettle",0);
            resutMap.put("waitAmount",0);
            resutMap.put("waitAll",0);
        }
        return ApiRes.ok(resutMap);
    }
}
