package com.jeequan.jeepay.mgr.service;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.AccountOperate;
import com.jeequan.jeepay.core.entity.CashoutRecord;
import com.jeequan.jeepay.core.entity.TransferOrder;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.exception.ChannelException;
import com.jeequan.jeepay.core.interfaces.paychannel.IRepayApiService;
import com.jeequan.jeepay.core.model.DBPaymentConfig;
import com.jeequan.jeepay.core.model.df.PaymentSign;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.AccountChangeInfo;
import com.jeequan.jeepay.db.entity.AccountFundInfo;
import com.jeequan.jeepay.db.entity.AccountInfo;
import com.jeequan.jeepay.service.impl.AccountInfoService;
import com.jeequan.jeepay.service.impl.SysConfigService;
import com.jeequan.jeepay.service.mapper.AccountChangeInfoMapper;
import com.jeequan.jeepay.service.mapper.AccountFundInfoMapper;
import io.lettuce.core.StrAlgoArgs;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * TODO
 * 渠道Api类Service
 * @author crystal
 * @date 2024/3/26 11:01
 */
@Service
@Slf4j
public class ChannelApiService {

    @Autowired private SysConfigService sysConfigService;
    @Autowired private AccountFundInfoMapper accountFundInfoMapper;
    @Autowired private AccountInfoService accountInfoService;

    /**
     * 付款
     * @param fundInfo
     * @return
     */
    public ChannelRetMsg payment(AccountFundInfo fundInfo) {
        DBPaymentConfig config = sysConfigService.getDbPaymentConfig();
        if(config == null){
            throw new BizException("打款参数未配置");
        }
        //调用一下签约
        IRepayApiService api = SpringBeansUtil.getBean(config.getPaymentType() + "RepayApiService", IRepayApiService.class);
        if(api == null){
            throw new BizException("未获取到付款接口");
        }
        api.preCheck(fundInfo.getMchNo(),fundInfo.getAccountType(),fundInfo.getChangeAmt());
        PaymentSign signParams = new PaymentSign(fundInfo.getExtra());
        //如果需要签约 则先调用签约
        if(api.isSign()){
            ChannelRetMsg signRetQuery = ChannelRetMsg.confirmFail();
            try {
                signRetQuery = api.querySign(signParams, config);
            }catch (ChannelException e){
                //如果签约查不出数据 则调用签约接口
            }
            if(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS != signRetQuery.getChannelState()){
                ChannelRetMsg signRetMsg = api.sign(signParams, config);
                if(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS != signRetMsg.getChannelState()){
                    throw ChannelException.sysError(signRetMsg.getChannelErrMsg());
                }
            }
        }
        CashoutRecord record = new CashoutRecord();
        record.setApplyAmount(fundInfo.getChangeAmt());
        record.setSettAccountBank(signParams.getBankName());
        record.setAuditRemark(fundInfo.getRemark());
        record.setSettAmount(fundInfo.getChangeAmt());
        record.setIdCard(signParams.getIdCard());
        record.setSettAccountType(fundInfo.getPayMethod());
        record.setSettAccountNo(signParams.getSettleNo());
        record.setTransferOrderId(fundInfo.getOrderId());
        record.setSettAccountName(signParams.getUserName());
        record.setBankPhone(signParams.getMobile());
        //如果签约正常 则走付款流程
        return api.payment(record, config);
    }

    /**
     * 确认操作
     * @param fundInfo
     */
    @Transactional(rollbackFor = Exception.class)
    public void confirm(AccountFundInfo fundInfo) {
        if(StringUtils.isEmpty(fundInfo.getOrderId())){
            throw new BizException("缺失流水号");
        }
        if(fundInfo.getState() == null){
            throw new BizException("操作类型状态不能为空");
        }
        AccountFundInfo ext = accountFundInfoMapper.selectById(fundInfo.getOrderId());
        if(ext == null){
            throw new BizException("未知的流水号");
        }
        if(AccountFundInfo.INIT != ext.getState() && AccountFundInfo.AUDIT != ext.getState()){
            throw new BizException("当前状态不支持该操作");
        }
        AccountOperate operate = new AccountOperate(ext.getAccountNo(),ext.getAmount(),ext.getChangeType(),ext.getChangeMethod(),ext.getOrderId(),fundInfo.getRemark());
        if(AccountFundInfo.FAIL == fundInfo.getState()){
            operate.setIsUpdateAccount(false);
            operate.setState(AccountFundInfo.FAIL);
            if(AccountFundInfo.ChangeType.CASH.getValue().byteValue() == ext.getChangeType()){
                operate.setIsUpdateAccount(true);
                operate.setChangeAmt(operate.getFinalAmt());
                operate.setChangeMethod(AccountFundInfo.ChangeMethod.REJECT.getValue());
            }
            if(StringUtils.isEmpty(fundInfo.getRemark())){
                throw new BizException("如果为驳回状态，请填写驳回备注");
            }
        }else{
            if(CS.AccountOperateType.CASH.getType().byteValue() == ext.getChangeType() && fundInfo.getMark() == null){
                throw new BizException("提现审核操作，需要指定打款类型");
            }
            operate.setMark(fundInfo.getMark());
            operate.setChangeAmt(ext.getFinalAmount());
            AccountFundInfo.ChangeType val = AccountFundInfo.ChangeType.getVal(ext.getChangeType());
            switch (val){
                case CASH:
                    operate.setState(fundInfo.getMark() == AccountFundInfo.FLEXIBLE ? AccountFundInfo.PAYMENT : AccountFundInfo.SUCCESS);
                    break;
                case RECHARGE:
                    if(AccountFundInfo.ChangeMethod.PUBIC.getValue().byteValue() == operate.getChangeMethod()){
                        operate.setIsUpdateAccount(true);
                        operate.setState(AccountFundInfo.SUCCESS);
                    }
                    break;
                default:
                    throw new BizException("暂不支持该操作类型");
            }
        }
        accountInfoService.upAccount(operate);
        if(operate.getState() == AccountFundInfo.PAYMENT){
            ext.setChangeAmt(operate.getChangeAmt());
            payment(ext);
        }
    }
}
