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

import com.zehong.common.core.exception.BusinessException;
import com.zehong.system.domain.TAccount;
import com.zehong.system.domain.TCashOperate;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * @author geng
 * 交易结算
 */
@Component
public class SettlementTrade {

    private static final Logger log = LoggerFactory.getLogger(SettlementTrade.class);

    private TTradeProject tradeProject;

    @Resource
    private TAccountMapper tAccountMapper;

    @Resource
    private TTradeProjectMapper tTradeProjectMapper;

    @Resource
    private TCashOperateMapper cashOperateMapper;

    /**
     * 可用账户结算
     */
    public void settleAbleAmount(TTradeProject tradeProject){
        this.tradeProject = tradeProject;
        //买方结算
        settleBuyerAbleAmount();
        //卖方结算
        settleSellerAbleAmount();
    }


    /**
     * 买方结算
     */
    private void settleBuyerAbleAmount() {
        TAccount account = getAccountInfo(this.tradeProject.getTradeDeptId());
        //判断买方可用额度是否为0
        if(account.getAbleAmount().compareTo(BigDecimal.ZERO) == 0){
            this.tradeProject.setPendingPayment(this.tradeProject.getDealPrice());
            return;
        }
        //买方可用额度为0，计算尾款
        BigDecimal pendingPayment = account.getAbleAmount().compareTo(tradeProject.getDealPrice()) == 1 ?
                new BigDecimal("0") :
                this.tradeProject.getDealPrice().subtract(account.getAbleAmount());
        this.tradeProject.setPendingPayment(pendingPayment);
        //买方可用额度计算
        BigDecimal payment = pendingPayment.compareTo(BigDecimal.ZERO) == 0 ?
                this.tradeProject.getDealPrice().negate() :
                account.getAbleAmount().negate();
        updateAccount(account,payment);
    }

    /**
     * 卖方结算
     */
    private void settleSellerAbleAmount() {
        TAccount account = getAccountInfo(this.tradeProject.getApplyDeptId());
        //进账
        BigDecimal incomeAmount = this.tradeProject.getDealPrice().subtract(this.tradeProject.getPendingPayment());
        //判断是否有进账
        if(incomeAmount.compareTo(BigDecimal.ZERO) == 1 && account.getAbleAmount().compareTo(BigDecimal.ZERO) == 0){
            //结算本部尾款
            List<TTradeProject> pendingPaymentInfo = tTradeProjectMapper.getTradePendingPaymentInfo(this.tradeProject.getApplyDeptId());
            for(TTradeProject project : pendingPaymentInfo){
                if(incomeAmount.compareTo(BigDecimal.ZERO) == 0){
                    return;
                }
                BigDecimal amount = updatePendingPayment(incomeAmount,project);
                //重新计算进账金额
                incomeAmount = incomeAmount.subtract(amount);
            }
        }
        //更新可用额度
        updateAccount(account,incomeAmount);
    }

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


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


    /**
     * 更新尾款信息
     * @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("1");//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;
    }


}
