package com.jsowell.pile.service.impl;

import com.jsowell.common.exception.BusinessException;
import com.jsowell.pile.domain.MemberAdapayRecord;
import com.jsowell.pile.mapper.MemberAdapayRecordMapper;
import com.jsowell.pile.service.MemberAdapayRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;

@Slf4j
@Service
public class MemberAdapayRecordServiceImpl implements MemberAdapayRecordService {

    @Resource
    private MemberAdapayRecordMapper memberAdapayRecordMapper;

    @Override
    public int insertSelective(MemberAdapayRecord record) {
        return memberAdapayRecordMapper.insertSelective(record);
    }

    @Override
    public MemberAdapayRecord selectByPrimaryKey(Integer id) {
        return memberAdapayRecordMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKeySelective(MemberAdapayRecord record) {
        return memberAdapayRecordMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateBatch(List<MemberAdapayRecord> list) {
        return memberAdapayRecordMapper.updateBatch(list);
    }

    @Override
    public int batchInsert(List<MemberAdapayRecord> list) {
        return memberAdapayRecordMapper.batchInsert(list);
    }

    @Override
    public int insertOrUpdate(MemberAdapayRecord record) {
        return memberAdapayRecordMapper.insertOrUpdate(record);
    }

    @Override
    public int insertOrUpdateSelective(MemberAdapayRecord record) {
        return memberAdapayRecordMapper.insertOrUpdateSelective(record);
    }

    /**
     * 查询会员的支付记录，按照支付成功时间正序
     *
     * @param memberId     会员id
     * @param scenarioType 支付订单/充值余额
     * @return 支付记录列表
     */
    @Override
    public List<MemberAdapayRecord> selectAdapayRecordList(String memberId, String scenarioType) {
        return memberAdapayRecordMapper.selectAdapayRecordList(memberId, scenarioType);
    }

    @Override
    public MemberAdapayRecord selectByPaymentId(String paymentId) {
        return memberAdapayRecordMapper.selectByPaymentId(paymentId);
    }

    /**
     * 查询会员可用余额充值记录
     *
     * @param memberId 会员id
     * @return
     */
    @Override
    public List<MemberAdapayRecord> selectAvailableBalance(String memberId) {
        return memberAdapayRecordMapper.selectAvailableBalance(memberId);
    }

    /**
     * 更新消费金额
     * 用来累计消费金额
     */
    @Override
    public void updateSpendAmount(String paymentId, BigDecimal spendAmount) {
        log.info("更新消费金额, paymentId:{}, 消费金额:{}", paymentId, spendAmount);
        MemberAdapayRecord record = selectByPaymentId(paymentId);
        if (record == null) {
            log.info("更新交易记录的消费金额和退款金额paymentId:{}, 查询为空", paymentId);
            return;
        }
        // 更新消费金额 = 累计消费的金额 - 本次消费的金额
        record.setSpendAmt(record.getSpendAmt().add(spendAmount));
        // 更新此笔交易单的剩余金额 = 支付金额 - 累计退款金额 - 累计消费金额 - 累计冻结金额
        BigDecimal balanceAmt = record.getPayAmt().subtract(record.getRefundAmt()).subtract(record.getSpendAmt()).subtract(record.getFreezeAmt());
        record.setBalanceAmt(balanceAmt);
        updateByPrimaryKeySelective(record);
    }

    /**
     * 解冻金额
     */
    @Override
    public void unfreezeAmount(String paymentId, BigDecimal unfreezeAmount) {
        log.info("解冻金额, paymentId:{}, 解冻金额:{}", paymentId, unfreezeAmount);
        MemberAdapayRecord record = selectByPaymentId(paymentId);
        if (record == null) {
            log.info("更新交易记录的消费金额和退款金额paymentId:{}, 查询为空", paymentId);
            return;
        }
        // 更新解冻金额 = 目前冻结的金额 - 需要解冻的金额
        record.setFreezeAmt(record.getFreezeAmt().subtract(unfreezeAmount));
        // 更新此笔交易单的剩余金额 = 支付金额 - 累计退款金额 - 累计消费金额 - 累计冻结金额
        BigDecimal balanceAmt = record.getPayAmt().subtract(record.getRefundAmt()).subtract(record.getSpendAmt()).subtract(record.getFreezeAmt());
        record.setBalanceAmt(balanceAmt);
        updateByPrimaryKeySelective(record);
    }

    /**
     * 解冻金额并更新消费金额
     * @param unfreezeAmount 解冻金额
     * @param spendAmount 消费金额
     */
    @Override
    public void unfreezeAmountAndUpdateSpendAmount(String paymentId, BigDecimal unfreezeAmount, BigDecimal spendAmount) {
        log.info("解冻金额并更新消费金额, paymentId:{}, 解冻金额:{}, 消费金额:{}", paymentId, unfreezeAmount, spendAmount);
        MemberAdapayRecord record = selectByPaymentId(paymentId);
        if (record == null) {
            log.info("更新交易记录的消费金额和退款金额paymentId:{}, 查询为空", paymentId);
            return;
        }
        // 更新解冻金额 = 目前冻结的金额 - 需要解冻的金额
        record.setFreezeAmt(record.getFreezeAmt().subtract(unfreezeAmount));
        // 更新消费金额 = 累计消费的金额 - 本次消费的金额
        record.setSpendAmt(record.getSpendAmt().add(spendAmount));
        // 更新此笔交易单的剩余金额 = 支付金额 - 累计退款金额 - 累计消费金额 - 累计冻结金额
        BigDecimal balanceAmt = record.getPayAmt().subtract(record.getRefundAmt()).subtract(record.getSpendAmt()).subtract(record.getFreezeAmt());
        record.setBalanceAmt(balanceAmt);
        updateByPrimaryKeySelective(record);
    }

    /**
     * 从冻结金额中退款
     * 部分解冻，并退款
     */
    @Override
    public void updateRefundAmountFromFreezeAmount(String paymentId, BigDecimal refundAmount) {
        log.info("部分解冻，并退款, paymentId:{}, 退款金额:{}", paymentId, refundAmount);
        // commonUpdateAmountMethod(paymentId, null, refundAmount, refundAmount.negate());
        MemberAdapayRecord record = selectByPaymentId(paymentId);
        if (record == null) {
            log.info("更新交易记录的消费金额和退款金额paymentId:{}, 查询为空", paymentId);
            return;
        }
        // 更新冻结金额 = 目前冻结的金额 - 需要解冻的金额
        record.setFreezeAmt(record.getFreezeAmt().subtract(refundAmount));
        // 更新消费金额 = 累计消费的金额 - 本次消费的金额
        record.setRefundAmt(record.getRefundAmt().add(refundAmount));
        // 更新此笔交易单的剩余金额 = 支付金额 - 累计退款金额 - 累计消费金额 - 累计冻结金额
        BigDecimal balanceAmt = record.getPayAmt().subtract(record.getRefundAmt()).subtract(record.getSpendAmt()).subtract(record.getFreezeAmt());
        record.setBalanceAmt(balanceAmt);
        updateByPrimaryKeySelective(record);
    }

    /**
     * 更新退款金额
     */
    @Override
    public void updateRefundAmount(String paymentId, BigDecimal refundAmount) {
        log.info("更新剩余金额, paymentId:{}, 退款金额:{}", paymentId, refundAmount);
        MemberAdapayRecord record = selectByPaymentId(paymentId);
        if (record == null) {
            log.info("更新交易记录的消费金额和退款金额paymentId:{}, 查询为空", paymentId);
            return;
        }
        // 更新消费金额 = 累计消费的金额 - 本次消费的金额
        record.setRefundAmt(record.getRefundAmt().add(refundAmount));
        // 更新此笔交易单的剩余金额 = 支付金额 - 累计退款金额 - 累计消费金额 - 累计冻结金额
        BigDecimal balanceAmt = record.getPayAmt().subtract(record.getRefundAmt()).subtract(record.getSpendAmt()).subtract(record.getFreezeAmt());
        record.setBalanceAmt(balanceAmt);
        updateByPrimaryKeySelective(record);
    }

    /**
     * 更新冻结金额
     */
    @Override
    public void updateFreezeAmount(String paymentId, BigDecimal freezeAmount) {
        log.info("更新冻结金额, paymentId:{}, 冻结金额:{}", paymentId, freezeAmount);
        MemberAdapayRecord record = selectByPaymentId(paymentId);
        if (record == null) {
            log.info("更新交易记录的消费金额和退款金额paymentId:{}, 查询为空", paymentId);
            return;
        }
        // 更新冻结金额 = 目前冻结的金额 - 需要解冻的金额
        record.setFreezeAmt(record.getFreezeAmt().add(freezeAmount));
        // 更新此笔交易单的剩余金额 = 支付金额 - 累计退款金额 - 累计消费金额 - 累计冻结金额
        BigDecimal balanceAmt = record.getPayAmt().subtract(record.getRefundAmt()).subtract(record.getSpendAmt()).subtract(record.getFreezeAmt());
        record.setBalanceAmt(balanceAmt);
        updateByPrimaryKeySelective(record);
    }

    /**
     * 更新交易记录的消费金额和退款金额
     *
     * @param paymentId    支付id
     * @param spendAmount  消费金额
     * @param refundAmount 退款金额
     * @param freezeAmount 冻结金额
     */
    @Override
    public void commonUpdateAmountMethod(String paymentId, BigDecimal spendAmount, BigDecimal refundAmount, BigDecimal freezeAmount) {
        MemberAdapayRecord record = selectByPaymentId(paymentId);
        if (record == null) {
            log.info("更新交易记录的消费金额和退款金额paymentId:{}, 查询为空", paymentId);
            return;
        }
        // 此时数据库中的值
        BigDecimal spendAmt = record.getSpendAmt();
        BigDecimal refundAmt = record.getRefundAmt();
        BigDecimal freezeAmt = record.getFreezeAmt();
        BigDecimal balanceAmt = record.getBalanceAmt();

        try {
            if (freezeAmount != null) {
                if (BigDecimal.ZERO.compareTo(freezeAmount) > 0) {
                    // 如果冻结金额传过来是负数，说明是解冻
                    if (freezeAmount.negate().compareTo(freezeAmt) > 0) {
                        throw new BusinessException("", "解冻金额大于冻结金额");
                    }
                    balanceAmt = balanceAmt.add(freezeAmount.negate()); // 剩余金额增加
                } else {
                    if (freezeAmount.compareTo(balanceAmt) > 0) {
                        throw new BusinessException("", "冻结金额大于剩余金额");
                    }
                }
                freezeAmt = freezeAmt.add(freezeAmount); // 冻结金额减少
                // 设置冻结金额 = 历史冻结金额 + 本次冻结金额
                record.setFreezeAmt(freezeAmt);
            }
            if (refundAmount != null) {
                if (refundAmount.compareTo(balanceAmt) > 0) {
                    throw new BusinessException("", "退款金额大于剩余金额");
                }
                // 设置退款金额 = 历史退款金额 + 本次退款金额
                refundAmt = refundAmt.add(refundAmount);
                record.setRefundAmt(refundAmt);
            }
            if (spendAmount != null) {
                if (spendAmount.compareTo(balanceAmt) > 0) {
                    throw new BusinessException("", "消费金额大于剩余金额");
                }
                // 设置消费金额 = 历史消费金额 + 本次消费金额
                spendAmt = spendAmt.add(spendAmount);
                record.setSpendAmt(spendAmt);
            }
            // 更新此笔交易单的剩余金额 = 支付金额 - 累计退款金额 - 累计消费金额 - 累计冻结金额
            balanceAmt = record.getPayAmt().subtract(refundAmt).subtract(spendAmt).subtract(freezeAmt);
            record.setBalanceAmt(balanceAmt);
            updateByPrimaryKeySelective(record);
        } catch (Exception e) {
            log.error("更新MemberAdapayRecord金额paymentId:{}, spendAmount:{}, refundAmount:{}, freezeAmount:{}", paymentId, spendAmount, refundAmount, freezeAmount);
            log.error("更新MemberAdapayRecord金额error", e);
        }
    }

    @Override
    public List<MemberAdapayRecord> selectAvailableFreeze(String memberId) {
        return memberAdapayRecordMapper.selectAvailableFreeze(memberId);
    }
}
