package com.jeequan.jeepay.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.db.entity.CashoutRecord;
import com.jeequan.jeepay.db.entity.InfoAccount;
import com.jeequan.jeepay.db.entity.InfoAccountHistory;
import com.jeequan.jeepay.db.entity.OrderProfitSettRecord;
import com.jeequan.jeepay.service.mapper.AgentInfoMapper;
import com.jeequan.jeepay.service.mapper.InfoAccountMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 * 钱包表 服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2022-03-12
 */
@Service
public class InfoAccountService extends ServiceImpl<InfoAccountMapper, InfoAccount> {

    @Autowired private InfoAccountHistoryService infoAccountHistoryService;
    @Autowired private AgentInfoMapper agentInfoMapper;


    /** 查询 */
    public InfoAccount queryById(String infoId, String sysType){
        return this.getOne(InfoAccount.gw().eq(InfoAccount::getInfoId, infoId).eq(InfoAccount::getInfoType, sysType));
    }

    /** 同时更新： 变动金额  & 不可用金额（判断是否足够）  **/
    public void changeBalanceAmountAndUnAmountWithEx(String infoId, String infoType, Long changeAmount){
        if(changeAmount == 0){
            return ;
        }
        if(baseMapper.changeBalanceAmountAndUnAmount(infoId, infoType, changeAmount) <= 0){
            throw new BizException("更新"+infoId+"账户余额失败！");
        }
    }

    /** 变动金额 （不判断是否足够）  **/
    public void changeBalanceAmountWithEx(String infoId, String infoType, Long changeAmount, boolean checkEnough){
        if(changeAmount == 0){
            return ;
        }
        if(baseMapper.changeBalanceAmount(infoId, infoType, changeAmount, checkEnough) <= 0){
            throw new BizException("更新"+infoId+"账户余额失败！");
        }
    }

    /** 变动不可用金额 （判断是否足够）
     *
     * 审核拒绝， 不验证是否金额为负数（可能为负数）
     * 发起提现申请： 校验金额不可为负数
     *
     * **/
    public void changeUnAmountWithEx(String infoId, String infoType, Long changeAmount, boolean checkEnough){
        if(changeAmount == 0){
            return ;
        }
        if(baseMapper.changeUnAmount(infoId, infoType, changeAmount, checkEnough) <= 0){
            throw new BizException("更新不可用余额失败，请检查余额是否充足！");
        }
    }

    /** 变动审核中金额 （判断是否足够）  **/
    public void changeAuditProfitAmountWithEx(String infoId, String infoType, Long changeAmount){
        if(changeAmount == 0){
            return ;
        }
        if(baseMapper.changeAuditProfitAmount(infoId, infoType, changeAmount) <= 0){
            throw new BizException("更新审核中余额失败，请检查余额是否充足！");
        }
    }

    /** 查询信息 **/
    public InfoAccount queryOne(String infoId, String infoType){
        return getOne(InfoAccount.gw()
                .select(InfoAccount::getInfoId, InfoAccount::getBalanceAmount, InfoAccount::getUnAmount, InfoAccount::getAuditProfitAmount)
                .eq(InfoAccount::getInfoId, infoId).eq(InfoAccount::getInfoType, infoType));
    }

    /** 查询商户账户信息 **/
    public InfoAccount queryMchAccount(String mchNo){
        return queryOne(mchNo, CS.SYS_ROLE_TYPE.MCH);
    }

    /** 查询服务商账户信息 **/
    public InfoAccount queryAgentAccount(String agentNo){
        return queryOne(agentNo, CS.SYS_ROLE_TYPE.AGENT);
    }

    /** 查询平台账户 **/
    public InfoAccount queryPlatformAccount(String infoId){
        return queryOne(infoId, CS.SYS_ROLE_TYPE.PLATFORM);
    }

    /** 初始化数据 **/
    public void initMchAccount(String mchNo){
        save(new InfoAccount().setInfoId(mchNo).setInfoType(CS.SYS_ROLE_TYPE.MCH));
    }

    /** 初始化数据 **/
    public void initAgentAccount(String agentNo){
        save(new InfoAccount().setInfoId(agentNo).setInfoType(CS.SYS_ROLE_TYPE.AGENT));
    }


    /**
     * 动账 & 保存 history
     * 根据订单的 profit字段。
     * opAccountType: 处理的账户类型：  钱包账户 或者  在途账户
     * 已知调用者： 计算在途佣金，   佣金 转 钱包
     * **/
    @Transactional
    public void changeAmountBySettProfit(OrderProfitSettRecord record, Byte opAccountType){

        // 动账金额
        Long changeAmount = record.getCalProfitAmount();

        // 无需计算 ( 支持小于 0 的计算 )
        if(changeAmount == 0 ){
            return ;
        }

        // 东账后 事务内 查询当前账户信息
        Long changedAfterAccountAmount = null;

        // 动账
        if(opAccountType == InfoAccountHistory.OP_ACCOUNT_TYPE_BALANCE){ // 钱包余额

            // 钱包账户  不判断是否大于0，钱包支持负数
            this.changeBalanceAmountWithEx(record.getInfoId(), record.getInfoType(), changeAmount, false);
            changedAfterAccountAmount = queryOne(record.getInfoId(), record.getInfoType()).getBalanceAmount();
        }
        else if(opAccountType == InfoAccountHistory.OP_ACCOUNT_TYPE_AUDIT_PROFIT){  // 在途钱包， 在途钱包没有负数的情况

            this.changeAuditProfitAmountWithEx(record.getInfoId(), record.getInfoType(), changeAmount);
            changedAfterAccountAmount = queryOne(record.getInfoId(), record.getInfoType()).getAuditProfitAmount();
        }

        // 历史记录表
        InfoAccountHistory history = commonHistory(changeAmount, changedAfterAccountAmount);
        history.setInfoId(record.getInfoId()); // infoId
        history.setInfoType(record.getInfoType()); // 系统类型： 参考：SYS_TYPE
        history.setInfoName(record.getInfoName()); // 名称快照
        history.setOpAccountType(opAccountType); // 变更账户类型： 1-钱包账户, 2-在途账户

        // 支付订单入账
        if(record.getCalType() == OrderProfitSettRecord.CAL_TYPE_PAY_ORDER){
            history.setBizType(InfoAccountHistory.BIZ_TYPE_PAY);
            history.setRelaBizOrderType(InfoAccountHistory.ORDER_TYPE_PAY); // 关联订单类型： 1-支付订单号, 2-退款订单号, 3-提现单号, 4-转账单号
            history.setRelaBizOrderId(record.getPayOrderId()); // 关联订单号

        } else if (record.getCalType() == OrderProfitSettRecord.CAL_TYPE_REFUND_ORDER) { // 退款
            history.setBizType(InfoAccountHistory.BIZ_TYPE_REFUND);
            history.setRelaBizOrderType(InfoAccountHistory.ORDER_TYPE_REFUND); // 关联订单类型： 1-支付订单号, 2-退款订单号, 3-提现单号
            history.setRelaBizOrderId(record.getRefundOrderId()); // 关联订单号

        } else if (record.getCalType() == OrderProfitSettRecord.CAL_TYPE_TRANS_ORDER) { // 转账业务订单
            history.setBizType(InfoAccountHistory.BIZ_TYPE_PAY);
            history.setRelaBizOrderType(InfoAccountHistory.ORDER_TYPE_TRANSFER); // 关联订单类型： 1-支付订单号, 2-退款订单号, 3-提现单号, 4-转账单号
            history.setRelaBizOrderId(record.getPayOrderId()); // 关联订单号
        }

        history.setSettId(record.getRid()); // 关联结算记录ID

        // 保存
        infoAccountHistoryService.save(history);

    }

    /** 变动账户 ：  服务商or 其他 提现申请成功 **/
    @Transactional
    public void changeAmountByCashoutAuditSuccess(CashoutRecord record){

        // 动账金额
        Long changeAmount = record.getApplyAmount();

        // 结算记录，金额需要大于 0
        if(changeAmount <= 0 ){
            return ;
        }

        // 动账： 钱包  && 减少不可用金额
        this.changeBalanceAmountAndUnAmountWithEx(record.getInfoId(), record.getInfoType(), (0 - changeAmount));

        // 东账后 事务内 查询当前账户信息
        Long changedAfterAccountAmount = queryOne(record.getInfoId(), record.getInfoType()).getBalanceAmount();

        // 历史记录表
        InfoAccountHistory history = commonHistory((0 - changeAmount), changedAfterAccountAmount);
        history.setInfoId(record.getInfoId()); // infoId
        history.setInfoType(record.getInfoType()); // 系统类型： 参考：SYS_TYPE
        history.setInfoName(record.getInfoName()); // 名称快照
        history.setOpAccountType(InfoAccountHistory.OP_ACCOUNT_TYPE_BALANCE); // 变更账户类型： 1-钱包账户, 2-在途账户
        history.setBizType(InfoAccountHistory.BIZ_TYPE_CASHOUT);
        history.setRelaBizOrderType(InfoAccountHistory.ORDER_TYPE_CASHOUT); // 关联订单类型： 1-支付订单号, 2-退款订单号, 3-提现单号
        history.setRelaBizOrderId(record.getRid() + ""); // 关联订单号

        // 保存
        infoAccountHistoryService.save(history);

    }

    private InfoAccountHistory commonHistory(Long changeAmount, Long changedAfterAccountAmount){

        InfoAccountHistory history = new InfoAccountHistory();
        history.setOpBeforeAmount(changedAfterAccountAmount - changeAmount); // 变动前账户余额, 单位：分
        history.setOpAmount(changeAmount); // 变动金额, 单位：分
        history.setOpAfterAmount(changedAfterAccountAmount); // 变动后账户余额, 单位：分
        return history;
    }



    /** 变动账户 ： 运营平台调账 **/
    @Transactional
    public void platformChange(String infoId, String infoType, Long changeAmount, String remark){

        // 动账金额
        if(changeAmount == 0 ){
            return ;
        }


        String infoName = "";
        if(CS.SYS_ROLE_TYPE.AGENT.equals(infoType)){
            infoName = agentInfoMapper.selectById(infoId).getAgentShortName();
        }

        // 动账： 钱包   不校验是否充足
        this.changeBalanceAmountWithEx(infoId, infoType, changeAmount, false);

        // 东账后 事务内 查询当前账户信息
        Long changedAfterAccountAmount = queryOne(infoId, infoType).getBalanceAmount();

        // 历史记录表
        InfoAccountHistory history = commonHistory(changeAmount, changedAfterAccountAmount);
        history.setInfoId(infoId); // infoId
        history.setInfoType(infoType); // 系统类型： 参考：SYS_TYPE
        history.setInfoName(infoName); // 名称快照
        history.setOpAccountType(InfoAccountHistory.OP_ACCOUNT_TYPE_BALANCE); // 变更账户类型： 1-钱包账户, 2-在途账户
        history.setBizType(InfoAccountHistory.BIZ_TYPE_PLATFORM_CHANGE);
        history.setRemark(remark);  // 备注

        // 保存
        infoAccountHistoryService.save(history);

    }




}
