package com.sunxung.factoring.service.financing.review.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunxung.factoring.component.enums.FinancingCurrentStageEnum;
import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.component.exception.ValidatorException;
import com.sunxung.factoring.component.util.*;
import com.sunxung.factoring.dict.impl.IncomeExpenditureTypeDict;
import com.sunxung.factoring.entity.ValidatorEntity;
import com.sunxung.factoring.entity.creditresolution.BusinessMeetsConditions;
import com.sunxung.factoring.entity.creditresolution.CreditResolution;
import com.sunxung.factoring.entity.creditresolution.LoanConditions;
import com.sunxung.factoring.entity.financing.apply.CFinancingBasicInfo;
import com.sunxung.factoring.entity.financing.contract.*;
import com.sunxung.factoring.entity.financing.review.*;
import com.sunxung.factoring.entity.project.ProjectInformation;
import com.sunxung.factoring.mapper.financing.review.ReviewQuotaDisburseApprovalMapper;
import com.sunxung.factoring.service.creditresolution.IBusinessMeetsConditionsService;
import com.sunxung.factoring.service.creditresolution.ICreditResolutionService;
import com.sunxung.factoring.service.creditresolution.ILoanConditionsService;
import com.sunxung.factoring.service.financing.apply.ICFinancingBasicInfoService;
import com.sunxung.factoring.service.financing.contract.*;
import com.sunxung.factoring.service.financing.review.*;
import com.sunxung.factoring.service.project.BusinessAssigneeService;
import com.sunxung.factoring.service.project.IProjectInformationService;
import com.sunxung.factoring.service.sys.UserService;
import com.sunxung.factoring.service.sys.flowable.FlowableService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description : 额度支用审批service实现类
 * @Author : L.Jia
 * @Date: 2024-01-21 11:32
 */
@Service("review_quota_disburse_approvalService")
public class ReviewQuotaDisburseApprovalServiceImpl extends ServiceImpl<ReviewQuotaDisburseApprovalMapper, ReviewQuotaDisburseApproval>
        implements ReviewQuotaDisburseApprovalService {

    @Autowired
    private ReviewQuotaDisburseService reviewQuotaDisburseService;
    @Autowired
    private ReviewQuotaDisburseApprovalMapper reviewQuotaDisburseApprovalMapper;
    @Autowired
    private IProjectInformationService projectInformationService;
    @Autowired
    private ICreditResolutionService creditResolutionService;
    @Autowired
    private IBusinessMeetsConditionsService businessMeetsConditionsService;
    @Autowired
    private ILoanConditionsService loanConditionsService;
    @Autowired
    private ReviewLoanConditionService reviewLoanConditionService;
    @Autowired
    private ReviewMasterContractService masterContractService;
    @Autowired
    private ReviewBasicContractService reviewBasicContractService;
    @Autowired
    private ReviewBasicContractChangeContentService reviewBasicContractChangeContentService;
    @Autowired
    private IContractBasicContractService contractBasicContractService;
    @Autowired
    private IContractBasicContractChangeContentService contractBasicContractChangeContentService;
    @Autowired
    private IContractBasicContractHisService contractBasicContractHisService;
    @Autowired
    private IContractBasicContractChangeContentHisService contractBasicContractChangeContentHisService;
    @Autowired
    private BusinessAssigneeService assigneeService;
    @Autowired
    private ReviewIncomeExpenditurePlanService reviewIncomeExpenditurePlanService;
    @Autowired
    private FlowableService flowableService;
    @Autowired
    private ICFinancingBasicInfoService financingBasicInfoService;
    @Autowired
    private IContractInfoService contractInfoService;
    @Autowired
    private UserService userService;

    @Override
    public ReviewQuotaDisburseApproval getToEditPageByDisburseId(Long id) {
        ReviewQuotaDisburse reviewQuotaDisburse = reviewQuotaDisburseService.getOne(new QueryWrapper<ReviewQuotaDisburse>()
                .eq("c_financing_basic_info_id", id)
                .eq("approval_conclusion", ConstantConversionUtil.APPROVAL_RESULT_PASS));
        if (reviewQuotaDisburse == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到对应额度支用信息");
        }
        ReviewQuotaDisburseApproval quotaDisburseApproval = new ReviewQuotaDisburseApproval();
        quotaDisburseApproval.setReviewQuotaDisburseId(reviewQuotaDisburse.getId());
        // 从额度支用节点获取收放款条件的数据
        getDateForQuotaDisburse(reviewQuotaDisburse.getId(), quotaDisburseApproval);
        // 从评审决议确认节点获取数据:获取指导性单笔业务满足条件
        quotaDisburseApproval.setGeneralConditionList(getDataFromReviewResolutionConfirmCondition(reviewQuotaDisburse.getId()));
        // 从评审决议确认节点获取数据:获取放款条件
        quotaDisburseApproval.setMeetingLoanConditionList(getDataFromReviewResolutionConfirm(reviewQuotaDisburse.getId()));
        return quotaDisburseApproval;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ReviewQuotaDisburseApproval editReviewQuotaDisburseApproval(ReviewQuotaDisburseApproval quotaDisburseApproval) {
        if (null != quotaDisburseApproval) {
            quotaDisburseApproval.setAssigneeId(ThreadLocalUtil.getUserId());
            if (null == quotaDisburseApproval.getId()) {
                // 新增
                add(quotaDisburseApproval);
            } else {
                // 修改
                update(quotaDisburseApproval);
            }
            if (quotaDisburseApproval.isVisible()) {
                ReviewQuotaDisburse quotaDisburse = reviewQuotaDisburseService.getById(quotaDisburseApproval.getReviewQuotaDisburseId());

                String key = ConstantUtil.FINANCING_APPLY;
                CFinancingBasicInfo financingBasicInfo = financingBasicInfoService.getById(quotaDisburse.getFinancingBasicInfoId());
                if (null == financingBasicInfo) {
                    throw new ValidatorException(CodeUtil.FAIL, "获取不到融资申请信息！");
                }
                Map<String, Object> msgVariables = new HashMap<>(2);
                msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, financingBasicInfo.getBusinessNumber());
                msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT, "业务编号为“" + financingBasicInfo.getBusinessNumber()
                        + "”的项目已inOut“"
                        + ConstantConversionUtil.flowBusinessKeyNames.get(quotaDisburse.getClass().getSimpleName())
                        + "—formBusiness”阶段，");

                Map<String, Object> procVariables = new HashMap<>(1);
                procVariables.put(ConstantUtil.CONTRACT_MAKING_CANDIDATE, assigneeService.getCandidateByBusiness(financingBasicInfo.getId(), key,
                        ConstantUtil.ASSIGNEE_LEGAL_SPECIALIST));

                String taskId = quotaDisburseApproval.getTaskId();
                List<Long> legalSpecialists = userService.findUserIdByRole(ConstantUtil.LEGAL_SPECIALIST);
                if (legalSpecialists == null || legalSpecialists.size() == 0) {
                    throw new ValidatorException(CodeUtil.FAIL, ConstantUtil.LEGAL_SPECIALIST + "角色内无任何用户！");
                }
                String conclusion = ConstantConversionUtil.processApprovalResult.get(quotaDisburseApproval.getApprovalConclusion()).equals("驳回") ?
                        "退回" : ConstantConversionUtil.processApprovalResult.get(quotaDisburseApproval.getApprovalConclusion());
                Boolean result = flowableService.completeMyTask(taskId, financingBasicInfo, procVariables,
                        conclusion, quotaDisburseApproval.getId(), msgVariables, key, legalSpecialists);
                if (result == null || !result) {
                    throw new ValidatorException(CodeUtil.FAIL, "额度支用审批提交时出错啦！");
                }

                // 额度支用审批通过且完成任务成功
                if (quotaDisburseApproval.getApprovalConclusion().equals(ConstantConversionUtil.APPROVAL_RESULT_PASS)) {
                    //修改融资申请当前阶段
                    financingBasicInfo.setCurrentStage(FinancingCurrentStageEnum.CONTRACT_MAKING.getCode());
                    financingBasicInfoService.updateById(financingBasicInfo);

                    ContractInfo contractInfo = new ContractInfo();
                    contractInfo.setQuotaDisburseBatch(quotaDisburse.getQuotaDisburseBatch());
                    contractInfo.setReviewQuotaDisburseId(quotaDisburse.getId());
                    contractInfo.setReviewQuotaDisburseApprovalId(quotaDisburseApproval.getId());
                    contractInfo.setBusinessNo(quotaDisburse.getBusinessNumber());

                    ReviewMasterContract masterContract = masterContractService.getOne(new QueryWrapper<ReviewMasterContract>()
                            .eq("review_quota_disburse_id", quotaDisburse.getId()));
                    if (null != masterContract) {
                        contractInfo.setContractNo(masterContract.getContractNo());
                    }
                    contractInfoService.save(contractInfo);

                    //新增三方协议信息
                    List<ReviewBasicContract> reviewBasicContractList = reviewBasicContractService.list(new QueryWrapper<ReviewBasicContract>()
                            .eq("review_quota_disburse_id", quotaDisburse.getId()));
                    if (CollectionUtil.isNotEmpty(reviewBasicContractList)) {
                        for (ReviewBasicContract reviewBasicContract : reviewBasicContractList) {
                            ContractBasicContract contractBasicContract = new ContractBasicContract(reviewBasicContract);
                            if (contractInfo.getId() != null) {
                                contractBasicContract.setContractInfoId(contractInfo.getId());
                            }
                            contractBasicContractService.save(contractBasicContract);
                            //保存历史
                            ContractBasicContractHis basicContractHis = new ContractBasicContractHis();
                            BeanUtils.copyProperties(contractBasicContract, basicContractHis, "id");
                            contractBasicContractHisService.save(basicContractHis);

                            List<ReviewBasicContractChangeContent> changeContentList = reviewBasicContractChangeContentService.list(new QueryWrapper<ReviewBasicContractChangeContent>()
                                    .eq("review_basic_contract_id", reviewBasicContract.getId()));
                            if (CollectionUtil.isNotEmpty(changeContentList)) {
                                changeContentList.stream().forEach(reviewBasicContractChangeContent -> {
                                    ContractBasicContractChangeContent contractBasicContractChangeContent = new ContractBasicContractChangeContent(reviewBasicContractChangeContent);
                                    contractBasicContractChangeContent.setContractBasicContractId(contractBasicContract.getId());
                                    contractBasicContractChangeContentService.save(contractBasicContractChangeContent);

                                    //保存历史
                                    ContractBasicContractChangeContentHis changeContentHis = new ContractBasicContractChangeContentHis();
                                    BeanUtils.copyProperties(contractBasicContractChangeContent, changeContentHis, "id");
                                    changeContentHis.setContractBasicContractHisId(basicContractHis.getId());
                                    contractBasicContractChangeContentHisService.save(changeContentHis);
                                });
                            }
                        }
                    }
                } else if (quotaDisburseApproval.getApprovalConclusion().equals(ConstantConversionUtil.APPROVAL_RESULT_BACK)) {
                    //修改融资申请当前阶段
                    financingBasicInfo.setCurrentStage(FinancingCurrentStageEnum.REVIEW_QUOTA_DISBURSE.getCode());
                    financingBasicInfoService.updateById(financingBasicInfo);
                }
            }
        }
        return quotaDisburseApproval;
    }

    @Override
    public ReviewQuotaDisburseApproval getView(Long id) {
        ReviewQuotaDisburseApproval quotaDisburseApproval = reviewQuotaDisburseApprovalMapper.selectById(id);
        if (quotaDisburseApproval == null || quotaDisburseApproval.getReviewQuotaDisburseId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到对应额度支用审批信息");
        }
        autoLoanCondition(quotaDisburseApproval);
        // 从评审决议确认节点获取数据:获取指导性单笔业务满足条件
        quotaDisburseApproval.setGeneralConditionList(getDataFromReviewResolutionConfirmCondition(quotaDisburseApproval.getReviewQuotaDisburseId()));
        // 从评审决议确认节点获取数据:获取放款条件
        quotaDisburseApproval.setMeetingLoanConditionList(getDataFromReviewResolutionConfirm(quotaDisburseApproval.getReviewQuotaDisburseId()));
        return quotaDisburseApproval;
    }

    /**
     * 新增额度支用审批信息
     *
     * @param quotaDisburseApproval
     */
    private ReviewQuotaDisburseApproval add(ReviewQuotaDisburseApproval quotaDisburseApproval) {
        if (quotaDisburseApproval.isVisible()) {
            ValidatorUtil.validator(ValidatorEntity.ValidatorType.ADD, quotaDisburseApproval);
        }
        reviewQuotaDisburseApprovalMapper.insert(quotaDisburseApproval);
        // 新增放款条件信息
        addLoanCondition(quotaDisburseApproval);
        return quotaDisburseApproval;
    }

    /**
     * 修改额度支用审批信息
     *
     * @param quotaDisburseApproval
     * @return
     */
    private ReviewQuotaDisburseApproval update(ReviewQuotaDisburseApproval quotaDisburseApproval) {
        if (quotaDisburseApproval.isVisible()) {
            ValidatorUtil.validator(ValidatorEntity.ValidatorType.UPDATE, quotaDisburseApproval);
        }
        reviewQuotaDisburseApprovalMapper.updateById(quotaDisburseApproval);
        // 修改放款条件信息
        reviewLoanConditionService.remove(new QueryWrapper<ReviewLoanCondition>().eq("review_quota_disburse_approval_id", quotaDisburseApproval.getId()));
        addLoanCondition(quotaDisburseApproval);
        return quotaDisburseApproval;
    }

    /**
     * 新增放款条件
     */
    private void addLoanCondition(ReviewQuotaDisburseApproval quotaDisburseApproval) {
        if (null != quotaDisburseApproval && null != quotaDisburseApproval.getId()) {
            List<ReviewLoanCondition> list = quotaDisburseApproval.getLoanConditionList();
            if (null != list && list.size() > 0) {
                for (ReviewLoanCondition loanCondition : list) {
                    loanCondition.setReviewQuotaDisburseApprovalId(quotaDisburseApproval.getId());
                    ValidatorUtil.validator(ValidatorEntity.ValidatorType.ADD, loanCondition);
                    reviewLoanConditionService.save(loanCondition);
                }
            }
        }
    }

    /**
     * 获取指导性单笔业务满足条件
     *
     * @param quotaDisburseId
     * @return
     */
    private List<BusinessMeetsConditions> getDataFromReviewResolutionConfirmCondition(Long quotaDisburseId) {
        List<BusinessMeetsConditions> list = new ArrayList<>();
        ReviewQuotaDisburse quotaDisburse = reviewQuotaDisburseService.getById(quotaDisburseId);
        if (null != quotaDisburse && null != quotaDisburse.getBusinessNumber()) {

            ProjectInformation projectInformation = projectInformationService.getOne(new QueryWrapper<ProjectInformation>()
                    .eq("business_number", quotaDisburse.getBusinessNumber()));
            if (projectInformation == null) {
                throw new BusinessException(CodeUtil.FAIL, "根据业务编号获取不到对应项目信息");
            }
            CreditResolution creditResolution = creditResolutionService.getByProjectInformationId(projectInformation.getId());
            if (null != creditResolution && null != creditResolution.getId()) {
                list = businessMeetsConditionsService.list(new QueryWrapper<BusinessMeetsConditions>().eq("credit_resolution_id", creditResolution.getId()));
            }
        }
        return list;
    }

    /**
     * 获取放款条件
     *
     * @param quotaDisburseId
     * @return
     */
    private List<LoanConditions> getDataFromReviewResolutionConfirm(Long quotaDisburseId) {
        List<LoanConditions> list = new ArrayList<>();
        ReviewQuotaDisburse quotaDisburse = reviewQuotaDisburseService.getById(quotaDisburseId);
        if (null != quotaDisburse && null != quotaDisburse.getBusinessNumber()) {

            ProjectInformation projectInformation = projectInformationService.getOne(new QueryWrapper<ProjectInformation>()
                    .eq("business_number", quotaDisburse.getBusinessNumber()));
            if (projectInformation == null) {
                throw new BusinessException(CodeUtil.FAIL, "根据业务编号获取不到对应项目信息");
            }
            CreditResolution creditResolution = creditResolutionService.getByProjectInformationId(projectInformation.getId());
            if (null != creditResolution && null != creditResolution.getId()) {
                list = loanConditionsService.list(new QueryWrapper<LoanConditions>().eq("credit_resolution_id", creditResolution.getId()));
            }
        }
        return list;
    }

    /**
     * 填充放款条件
     *
     * @param quotaDisburseApproval
     */
    private void autoLoanCondition(ReviewQuotaDisburseApproval quotaDisburseApproval) {
        if (null != quotaDisburseApproval && null != quotaDisburseApproval.getId()) {
            List<ReviewLoanCondition> list = reviewLoanConditionService.list(new QueryWrapper<ReviewLoanCondition>()
                    .eq("review_quota_disburse_approval_id", quotaDisburseApproval.getId()));
            if (null != list && list.size() > 0) {
                quotaDisburseApproval.setLoanConditionList(list);
            }
        }
    }

    /**
     * 填充授信决议条件
     *
     * @param quotaDisburseApproval
     */
    private void autoMeetingLoan(ReviewQuotaDisburseApproval quotaDisburseApproval) {
        if (null != quotaDisburseApproval && null != quotaDisburseApproval.getReviewQuotaDisburseId()) {
            List<BusinessMeetsConditions> businessMeetsConditionsList = getDataFromReviewResolutionConfirmCondition(quotaDisburseApproval.getReviewQuotaDisburseId());
            if (CollectionUtil.isNotEmpty(businessMeetsConditionsList)) {
                quotaDisburseApproval.setGeneralConditionList(businessMeetsConditionsList);
            }
            List<LoanConditions> loanConditionsList = getDataFromReviewResolutionConfirm(quotaDisburseApproval.getReviewQuotaDisburseId());
            if (CollectionUtil.isNotEmpty(loanConditionsList)) {
                quotaDisburseApproval.setMeetingLoanConditionList(loanConditionsList);
            }
        }
    }


    /**
     * 获取收放款条件数据
     *
     * @param quotaDisburseId
     * @param quotaDisburseApproval
     */
    private void getDateForQuotaDisburse(Long quotaDisburseId, ReviewQuotaDisburseApproval quotaDisburseApproval) {
        // 设置放款条件
        List<ReviewIncomeExpenditurePlan> planList = reviewIncomeExpenditurePlanService.list(new QueryWrapper<ReviewIncomeExpenditurePlan>()
                .eq("review_quota_disburse_id", quotaDisburseId).isNotNull("loan"));
        if (CollectionUtil.isNotEmpty(planList)) {
            List<ReviewLoanCondition> loanConditionList = new ArrayList<>();
            quotaDisburseApproval.setCurrencyCode(planList.get(0).getCurrencyCode());
            planList.stream().filter(e -> e.getLoan() != null && IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode().equals(e.getIncomeExpenditureType()))
                    .forEach((plan) -> loanConditionList.add(new ReviewLoanCondition(plan)));
            quotaDisburseApproval.setLoanConditionList(loanConditionList);
        }
    }
}
