package com.zehong.system.service.impl.debitSettlement;

import com.zehong.common.core.exception.BusinessException;
import com.zehong.system.domain.TAccount;
import com.zehong.system.domain.TCashOperate;
import com.zehong.system.domain.TDebitCredit;
import com.zehong.system.domain.TTradeProject;
import com.zehong.system.mapper.TAccountMapper;
import com.zehong.system.mapper.TCashOperateMapper;
import com.zehong.system.mapper.TTradeProjectMapper;
import io.jsonwebtoken.lang.Collections;
import org.springframework.stereotype.Component;

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

/**
 * @author geng
 * 借贷账户结算
 */
@Component
public class SettlementDebit {

    @Resource
    private TAccountMapper tAccountMapper;

    @Resource
    private TCashOperateMapper cashOperateMapper;

    private TDebitCredit tDebitCredit;

    @Resource
    private TTradeProjectMapper tTradeProjectMapper;

    /**
     * 借贷结算
     * @param tDebitCredit 借贷实体
     */
    public void settlementDebit(TDebitCredit tDebitCredit){
        this.tDebitCredit = tDebitCredit;
        //出借部门结算
        lendDeptSettlement(tDebitCredit.getLendDeptId(),tDebitCredit.getLittleTotal(),"5");
        //借贷部门结算
        debitDeptSettlement(tDebitCredit.getDebitDeptId(),tDebitCredit.getLittleTotal(),"6");
    }

    /**
     * 还款
     * @param tDebitCredit 借贷实体
     */
    public void repayment(TDebitCredit tDebitCredit){
        this.tDebitCredit = tDebitCredit;
        //计算还款日期
        long time = tDebitCredit.getExpectedRepaymentDate().getTime() - tDebitCredit.getSumInterestDate().getTime();
        long days = Math.round(((double)time) / 1000 / 60 / 60 / 24);
        //还款部门
        BigDecimal repayAmount = tDebitCredit.getLittleTotal().multiply( new BigDecimal(1 + 0.08/360 * days)).setScale(2, RoundingMode.HALF_UP);
        tDebitCredit.setRealPaymentDate(new Date());
        tDebitCredit.setRealPaymentAcount(repayAmount);
        lendDeptSettlement(tDebitCredit.getDebitDeptId(),repayAmount,"7");
        //还款进账部门
        debitDeptSettlement(tDebitCredit.getLendDeptId(),repayAmount,"8");
    }

    /**
     * 出借部门结算
     * @param deptId 部门账户
     * @param amount 金额
     * @param operatorType 操作类型
     */
    private void lendDeptSettlement(Long deptId, BigDecimal amount,String operatorType){
        TAccount account = getAccountInfo(deptId);
        if(account.getAbleAmount().compareTo(amount) == -1){
            throw new BusinessException("出借或还款账户金额不足！");
        }
        updateAccount(account,amount.negate(),operatorType);
    }

    /**
     * 借贷部门结算
     * @param deptId 部门账户
     * @param amount 金额
     * @param operatorType 操作类型
     */
    private void debitDeptSettlement(Long deptId, BigDecimal amount,String operatorType){
        TAccount account = getAccountInfo(deptId);
        //结算本部尾款
        List<TTradeProject> pendingPaymentInfo = tTradeProjectMapper.getTradePendingPaymentInfo(deptId);
        for(TTradeProject project : pendingPaymentInfo){
            if(amount.compareTo(BigDecimal.ZERO) == 0){
                return;
            }
            BigDecimal changeAmount = updatePendingPayment(amount,project);
            //重新计算进账金额
            amount = amount.subtract(changeAmount);
        }

        //更新可用额度
        updateAccount(account,amount,operatorType);
    }


    /**
     * 更新账户可用金额
     * @param tAccount 账户信息
     * @param  amount 账户变动金额
     * @param operatorType 操作类型
     */
    private void updateAccount(TAccount tAccount, BigDecimal amount,String operatorType){
        if(amount.compareTo(BigDecimal.ZERO) == 0) return;
        tAccount.setAbleAmount(tAccount.getAbleAmount().add(amount));
        tAccountMapper.updateTAccount(tAccount);
        //更新资金变动日志
        TCashOperate operate = OperatorParam(tAccount.getDeptId(),amount,this.tDebitCredit.getDebitId().toString());
        //1.交易单 2.借支单 3.外部采购单 4.借贷单
        operate.setDocumentType("4");
        operate.setOperateType(operatorType);
        cashOperateMapper.insertTCashOperate(operate);
    }

    /**
     * 获取账户信息
     * @param deptId
     * @return
     */
    private TAccount getAccountInfo(Long deptId){
        TAccount tAccount = new TAccount();
        tAccount.setDeptId(deptId);
        List<TAccount> accounts =  tAccountMapper.selectTAccountList(tAccount);
        assert !Collections.isEmpty(accounts) : "部门资金账户不能为空，部门id:" + deptId;
        return accounts.get(0);
    }

    /**
     * 更新尾款信息
     * @param incomeAmount 进账金额
     * @param project 交易项目
     */
    private BigDecimal updatePendingPayment(BigDecimal incomeAmount,TTradeProject project){
        //资金变动金额
        BigDecimal amount = incomeAmount.compareTo(project.getPendingPayment()) == 1 ? project.getPendingPayment() : incomeAmount;
        //尾款
        BigDecimal pendingPayment = incomeAmount.compareTo(project.getPendingPayment()) == -1 ? project.getPendingPayment().subtract(incomeAmount) : new BigDecimal("0");
        project.setPendingPayment(pendingPayment);
        tTradeProjectMapper.updateTTradeProject(project);
        //更新资金变动日志
        TCashOperate operate = OperatorParam(project.getTradeDeptId(),amount,project.getTradeId().toString());
        operate.setOperateType("3");
        operate.setDocumentType("4");//1.交易单 2.借支单 3.外部采购单 4.借贷单
        cashOperateMapper.insertTCashOperate(operate);
        return amount;
    }


    /**
     *
     * @param deptId 部门id
     * @param amount 变动金额
     * @param receiptNum 单据号
     * @return
     */
    private TCashOperate OperatorParam (Long deptId,BigDecimal amount,String receiptNum){
        TCashOperate operate = new TCashOperate();
        operate.setOperateDeptId(deptId);
        operate.setOperateAmount(amount.compareTo(BigDecimal.ZERO) == 1?amount:amount.abs());
        operate.setOperateTime(new Date());
        operate.setRelationDoc(receiptNum);
        return operate;
    }

}
