package cn.palmte.work.service;

import cn.palmte.work.bean.ApproveStatusEnum;
import cn.palmte.work.bean.EstimateBean;
import cn.palmte.work.bean.ProjectConfigBean;
import cn.palmte.work.bean.StatusEnum;
import cn.palmte.work.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.jfunc.common.db.utils.Pagination;
import top.jfunc.common.utils.CollectionUtil;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 项目概算service
 * @author xiongshiyan at 2021/10/29 , contact me with email yanshixiong@126.com or phone 15208384257
 */
@Service
public class ProjectEstimateService {
    @Autowired
    private ProjectEstimateIncomeRepository projectEstimateIncomeRepository;
    @Autowired
    private ProjectEstimateCostRepository projectEstimateCostRepository;
    @Autowired
    private ProjectEstimateCostManageRepository projectEstimateCostManageRepository;
    @Autowired
    private ProjectInstanceService projectInstanceService;
    @Autowired
    private ActTaskDefService actTaskDefService;
    @Autowired
    private ProjectService projectService;
    @Autowired
    private ProjectRepository projectRepository;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private Pagination pagination;
    @Autowired
    private ProjectVisibleRepository projectVisibleRepository;

    public void clearEstimate(Project project){
        List<ProjectEstimateIncome> incomes = projectEstimateIncomeRepository.findAllByProjectIdEquals(project.getId());
        if(CollectionUtil.isNotEmpty(incomes)){
            projectEstimateIncomeRepository.deleteInBatch(incomes);
        }

        List<ProjectEstimateCost> costs = projectEstimateCostRepository.findAllByProjectIdEquals(project.getId());
        if(CollectionUtil.isNotEmpty(costs)){
            projectEstimateCostRepository.deleteInBatch(costs);
        }

        List<ProjectEstimateCostManage> costManages = projectEstimateCostManageRepository.findAllByProjectIdEquals(project.getId());
        if(CollectionUtil.isNotEmpty(costManages)){
            projectEstimateCostManageRepository.deleteInBatch(costManages);
        }

    }

    public void saveEstimate(Project project, EstimateBean estimateBean){
        //收入记录
        income(project, estimateBean);
        //成本记录
        cost(project, estimateBean);
        //管理记录
        costManage(project, estimateBean);
    }

    public void deleteEstimate(int projectId){
        //删除收入记录
        projectEstimateIncomeRepository.deleteByProjectId(projectId);
        //删除成本记录
        projectEstimateCostRepository.deleteByProjectId(projectId);
        //删除管理记录
        projectEstimateCostManageRepository.deleteByProjectId(projectId);
    }

    private void cost(Project project, EstimateBean estimateBean) {
        ProjectEstimateCost projectEstimateCostDevice = new ProjectEstimateCost();
        projectEstimateCostDevice.setProjectId(project.getId());
        projectEstimateCostDevice.setFee(ProjectEstimateCost.FEE_PURCHASE);
        projectEstimateCostDevice.setType(ProjectEstimateCost.TYPE_DEVICE);
        projectEstimateCostDevice.setCostTaxInclude(estimateBean.getCostPurchaseDeviceTaxInclude());
        projectEstimateCostDevice.setCostTaxExclude(estimateBean.getCostPurchaseDeviceTaxExclude());
        projectEstimateCostDevice.setTaxRate(estimateBean.getCostPurchaseDeviceSelect());
        projectEstimateCostRepository.saveAndFlush(projectEstimateCostDevice);


        ProjectEstimateCost projectEstimateCostBuild = new ProjectEstimateCost();
        projectEstimateCostBuild.setProjectId(project.getId());
        projectEstimateCostBuild.setFee(ProjectEstimateCost.FEE_PURCHASE);
        projectEstimateCostBuild.setType(ProjectEstimateCost.TYPE_BUILDING);
        projectEstimateCostBuild.setCostTaxInclude(estimateBean.getCostPurchaseBuildTaxInclude());
        projectEstimateCostBuild.setCostTaxExclude(estimateBean.getCostPurchaseBuildTaxExclude());
        projectEstimateCostBuild.setTaxRate(estimateBean.getCostPurchaseBuildSelect());
        projectEstimateCostRepository.saveAndFlush(projectEstimateCostBuild);

        ProjectEstimateCost projectEstimateCostService = new ProjectEstimateCost();
        projectEstimateCostService.setProjectId(project.getId());
        projectEstimateCostService.setFee(ProjectEstimateCost.FEE_PURCHASE);
        projectEstimateCostService.setType(ProjectEstimateCost.TYPE_SERVICE);
        projectEstimateCostService.setCostTaxInclude(estimateBean.getCostPurchaseServiceTaxInclude());
        projectEstimateCostService.setCostTaxExclude(estimateBean.getCostPurchaseServiceTaxExclude());
        projectEstimateCostService.setTaxRate(estimateBean.getCostPurchaseServiceSelect());
        projectEstimateCostRepository.saveAndFlush(projectEstimateCostService);

        ProjectEstimateCost projectEstimateCostOther = new ProjectEstimateCost();
        projectEstimateCostOther.setProjectId(project.getId());
        projectEstimateCostOther.setFee(ProjectEstimateCost.FEE_PURCHASE);
        projectEstimateCostOther.setType(ProjectEstimateCost.TYPE_OTHER);
        projectEstimateCostOther.setCostTaxInclude(estimateBean.getCostPurchaseOtherTaxInclude());
        projectEstimateCostOther.setCostTaxExclude(estimateBean.getCostPurchaseOtherTaxExclude());
        projectEstimateCostOther.setTaxRate(estimateBean.getCostPurchaseOtherSelect());
        projectEstimateCostRepository.saveAndFlush(projectEstimateCostOther);

        ProjectEstimateCost projectEstimateCostProject = new ProjectEstimateCost();
        projectEstimateCostProject.setProjectId(project.getId());
        projectEstimateCostProject.setFee(ProjectEstimateCost.FEE_PROJECT_MANAGE);
        projectEstimateCostProject.setType(ProjectEstimateCost.TYPE_PROJECT_MANAGE);
        /*projectEstimateCostProject.setCostTaxInclude(estimateBean.getCostProjectManageTaxInclude());*/
        projectEstimateCostProject.setCostTaxExclude(estimateBean.getCostProjectManageTaxExclude());
        projectEstimateCostRepository.saveAndFlush(projectEstimateCostProject);

        ProjectEstimateCost projectEstimateCostOtherOther = new ProjectEstimateCost();
        projectEstimateCostOtherOther.setProjectId(project.getId());
        projectEstimateCostOtherOther.setFee(ProjectEstimateCost.FEE_OTHER);
        projectEstimateCostOtherOther.setType(ProjectEstimateCost.TYPE_OTHER_OTHER);
        projectEstimateCostOtherOther.setCostTaxInclude(estimateBean.getCostOtherOtherTaxInclude());
        projectEstimateCostOtherOther.setCostTaxExclude(estimateBean.getCostOtherOtherTaxExclude());
        projectEstimateCostOtherOther.setTaxRate(estimateBean.getCostOtherOtherSelect());
        projectEstimateCostRepository.saveAndFlush(projectEstimateCostOtherOther);

    }
    private void costManage(Project project, EstimateBean estimateBean) {
        ProjectEstimateCostManage projectEstimateCostZijin = new ProjectEstimateCostManage();
        projectEstimateCostZijin.setProjectId(project.getId());
        projectEstimateCostZijin.setType(ProjectEstimateCostManage.TYPE_EXPROPRIATION);
        projectEstimateCostZijin.setCostTaxExclude(estimateBean.getCostExpropriationTaxExclude());
        projectEstimateCostManageRepository.saveAndFlush(projectEstimateCostZijin);

        ProjectEstimateCostManage projectEstimateCostManage = new ProjectEstimateCostManage();
        projectEstimateCostManage.setProjectId(project.getId());
        projectEstimateCostManage.setType(ProjectEstimateCostManage.TYPE_COMPANY_MANAGE);
        projectEstimateCostManage.setCostTaxExclude(estimateBean.getCostCompanyManageTaxExclude());
        projectEstimateCostManageRepository.saveAndFlush(projectEstimateCostManage);
    }
    private void income(Project project, EstimateBean estimateBean) {
        ProjectEstimateIncome projectEstimateIncomeDevice = new ProjectEstimateIncome();
        projectEstimateIncomeDevice.setProjectId(project.getId());
        projectEstimateIncomeDevice.setType(ProjectEstimateIncome.TYPE_DEVICE);
        projectEstimateIncomeDevice.setIncomeTaxInclude(estimateBean.getIncomeDeviceTaxInclude());
        projectEstimateIncomeDevice.setIncomeTaxExclude(estimateBean.getIncomeDeviceTaxExclude());
        projectEstimateIncomeDevice.setTaxRate(estimateBean.getIncomeDeviceSelect());
        projectEstimateIncomeRepository.saveAndFlush(projectEstimateIncomeDevice);

        ProjectEstimateIncome projectEstimateIncomeEngineer = new ProjectEstimateIncome();
        projectEstimateIncomeEngineer.setProjectId(project.getId());
        projectEstimateIncomeEngineer.setType(ProjectEstimateIncome.TYPE_ENGINEER);
        projectEstimateIncomeEngineer.setIncomeTaxInclude(estimateBean.getIncomeEngineerTaxInclude());
        projectEstimateIncomeEngineer.setIncomeTaxExclude(estimateBean.getIncomeEngineerTaxExclude());
        projectEstimateIncomeEngineer.setTaxRate(estimateBean.getIncomeEngineerSelect());
        projectEstimateIncomeRepository.saveAndFlush(projectEstimateIncomeEngineer);

        ProjectEstimateIncome projectEstimateIncomeService = new ProjectEstimateIncome();
        projectEstimateIncomeService.setProjectId(project.getId());
        projectEstimateIncomeService.setType(ProjectEstimateIncome.TYPE_SERVICE);
        projectEstimateIncomeService.setIncomeTaxInclude(estimateBean.getIncomeServiceTaxInclude());
        projectEstimateIncomeService.setIncomeTaxExclude(estimateBean.getIncomeServiceTaxExclude());
        projectEstimateIncomeService.setTaxRate(estimateBean.getIncomeServiceSelect());
        projectEstimateIncomeRepository.saveAndFlush(projectEstimateIncomeService);
    }


    public EstimateBean getEstimate(Project project) {
        EstimateBean estimateBean = new EstimateBean();
        List<ProjectEstimateIncome> incomes = projectEstimateIncomeRepository.findAllByProjectIdEquals(project.getId());

        if(CollectionUtil.isNotEmpty(incomes)){
            ProjectEstimateIncome projectEstimateIncomeDevice = incomes.stream().filter(d -> d.getType() == ProjectEstimateIncome.TYPE_DEVICE).collect(Collectors.toList()).get(0);
            estimateBean.setIncomeDeviceTaxInclude(projectEstimateIncomeDevice.getIncomeTaxInclude());
            estimateBean.setIncomeDeviceTaxExclude(projectEstimateIncomeDevice.getIncomeTaxExclude());
            estimateBean.setIncomeDeviceSelect(projectEstimateIncomeDevice.getTaxRate());

            ProjectEstimateIncome projectEstimateIncomeEngineer = incomes.stream().filter(d -> d.getType() == ProjectEstimateIncome.TYPE_ENGINEER).collect(Collectors.toList()).get(0);
            estimateBean.setIncomeEngineerTaxInclude(projectEstimateIncomeEngineer.getIncomeTaxInclude());
            estimateBean.setIncomeEngineerTaxExclude(projectEstimateIncomeEngineer.getIncomeTaxExclude());
            estimateBean.setIncomeEngineerSelect(projectEstimateIncomeEngineer.getTaxRate());

            ProjectEstimateIncome projectEstimateIncomeService = incomes.stream().filter(d -> d.getType() == ProjectEstimateIncome.TYPE_SERVICE).collect(Collectors.toList()).get(0);
            estimateBean.setIncomeServiceTaxInclude(projectEstimateIncomeService.getIncomeTaxInclude());
            estimateBean.setIncomeServiceTaxExclude(projectEstimateIncomeService.getIncomeTaxExclude());
            estimateBean.setIncomeServiceSelect(projectEstimateIncomeService.getTaxRate());
        }


        List<ProjectEstimateCost> costs = projectEstimateCostRepository.findAllByProjectIdEquals(project.getId());

        if(CollectionUtil.isNotEmpty(costs)){
            ProjectEstimateCost projectEstimateCostDevice = costs.stream().filter(d -> d.getType() == ProjectEstimateCost.TYPE_DEVICE).collect(Collectors.toList()).get(0);
            estimateBean.setCostPurchaseDeviceTaxInclude(projectEstimateCostDevice.getCostTaxInclude());
            estimateBean.setCostPurchaseDeviceTaxExclude(projectEstimateCostDevice.getCostTaxExclude());
            estimateBean.setCostPurchaseDeviceSelect(projectEstimateCostDevice.getTaxRate());

            ProjectEstimateCost projectEstimateCostBuild = costs.stream().filter(d -> d.getType() == ProjectEstimateCost.TYPE_BUILDING).collect(Collectors.toList()).get(0);
            estimateBean.setCostPurchaseBuildTaxInclude(projectEstimateCostBuild.getCostTaxInclude());
            estimateBean.setCostPurchaseBuildTaxExclude(projectEstimateCostBuild.getCostTaxExclude());
            estimateBean.setCostPurchaseBuildSelect(projectEstimateCostBuild.getTaxRate());

            ProjectEstimateCost projectEstimateCostService = costs.stream().filter(d -> d.getType() == ProjectEstimateCost.TYPE_SERVICE).collect(Collectors.toList()).get(0);
            estimateBean.setCostPurchaseServiceTaxInclude(projectEstimateCostService.getCostTaxInclude());
            estimateBean.setCostPurchaseServiceTaxExclude(projectEstimateCostService.getCostTaxExclude());
            estimateBean.setCostPurchaseServiceSelect(projectEstimateCostService.getTaxRate());

            ProjectEstimateCost projectEstimateCostOther = costs.stream().filter(d -> d.getType() == ProjectEstimateCost.TYPE_OTHER).collect(Collectors.toList()).get(0);
            estimateBean.setCostPurchaseOtherTaxInclude(projectEstimateCostOther.getCostTaxInclude());
            estimateBean.setCostPurchaseOtherTaxExclude(projectEstimateCostOther.getCostTaxExclude());
            estimateBean.setCostPurchaseOtherSelect(projectEstimateCostOther.getTaxRate());

            ProjectEstimateCost projectEstimateCostProjectManage = costs.stream().filter(d -> d.getType() == ProjectEstimateCost.TYPE_PROJECT_MANAGE).collect(Collectors.toList()).get(0);
        /*estimateBean.setCostProjectManageTaxInclude(projectEstimateCostProjectManage.getCostTaxInclude());*/
            estimateBean.setCostProjectManageTaxExclude(projectEstimateCostProjectManage.getCostTaxExclude());

            ProjectEstimateCost projectEstimateCostOtherOther = costs.stream().filter(d -> d.getType() == ProjectEstimateCost.TYPE_OTHER_OTHER).collect(Collectors.toList()).get(0);
            estimateBean.setCostOtherOtherTaxInclude(projectEstimateCostOtherOther.getCostTaxInclude());
            estimateBean.setCostOtherOtherTaxExclude(projectEstimateCostOtherOther.getCostTaxExclude());
            estimateBean.setCostOtherOtherSelect(projectEstimateCostOtherOther.getTaxRate());

        }


        List<ProjectEstimateCostManage> manages = projectEstimateCostManageRepository.findAllByProjectIdEquals(project.getId());
        if(CollectionUtil.isNotEmpty(manages)){
            ProjectEstimateCostManage costManageExpropriation = manages.stream().filter(d -> d.getType() == ProjectEstimateCostManage.TYPE_EXPROPRIATION).collect(Collectors.toList()).get(0);
            if(costManageExpropriation.getCostTaxExclude() == null){
                costManageExpropriation.setCostTaxExclude(new BigDecimal(0));
            }
            estimateBean.setCostExpropriationTaxExclude(costManageExpropriation.getCostTaxExclude());

            ProjectEstimateCostManage costManageCompany = manages.stream().filter(d -> d.getType() == ProjectEstimateCostManage.TYPE_COMPANY_MANAGE).collect(Collectors.toList()).get(0);
            if(costManageCompany.getCostTaxExclude() == null){
                costManageCompany.setCostTaxExclude(new BigDecimal(0));
            }
            estimateBean.setCostCompanyManageTaxExclude(costManageCompany.getCostTaxExclude());
        }

        return estimateBean;
    }



    /**
     * 新增概算保存项目并发起审核
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public Project estimateAddSaveAndApprove(Project project,
                                             EstimateBean estimateBean,
                                             Admin admin) throws Exception {
        Project p = estimateAddSave(project, estimateBean, admin, ApproveStatusEnum.APPROVAL_PENDING);

        //projectInstanceService.startEstimateProcessInstance(p, admin);

        estimateApprove(0, p, admin);

        return project;
    }
    /**
     * 新增概算保存项目
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public Project estimateAddSave(Project project,
                                   EstimateBean estimateBean,
                                   Admin admin,
                                   ApproveStatusEnum approveStatusEnum) {
        Project p = projectService.addProject(project, admin, approveStatusEnum);
        saveEstimate(p, estimateBean);

        return p;
    }
    /**
     * 编辑概算保存项目并发起审核
     */
//    @Transactional(rollbackFor = RuntimeException.class)
    public void estimateEditSaveAndApprove(Project project,
                                           Project projectInDb,
                                           EstimateBean estimateBean,
                                           Admin admin) throws Exception {

        Integer approveStatusEstimate = projectInDb.getApproveStatusEstimate();

        estimateEditSave(project, projectInDb, estimateBean, admin, ApproveStatusEnum.APPROVAL_PENDING);

        estimateApprove(approveStatusEstimate, projectInDb, admin);
    }

    public void estimateApprove(Integer approveStatusEstimate, Project projectInDb, Admin admin) throws Exception {
        projectInstanceService.startEstimateProcessInstance(projectInDb, admin);
        int type = projectInDb.getType();
        List<SysUserRole> userIds = new ArrayList<>();
        if (type == 1) {
            String sql = "select sur.user_id from sys_role sr left join sys_user_role sur on sr.id = sur.role_id where sr.is_deleted = 0 and sur.is_deleted = 0 and sr.level in (1,2,3,4,5,6)";
            userIds = pagination.find(sql, SysUserRole.class);
        } else if (type == 2) {
            String sql = "select sur.user_id from sys_role sr left join sys_user_role sur on sr.id = sur.role_id where sr.is_deleted = 0 and sur.is_deleted = 0 and sr.level in (1,2,3,5,6)";
            userIds = pagination.find(sql, SysUserRole.class);
        } else if (type == 3) {
            String sql = "select sur.user_id from sys_role sr left join sys_user_role sur on sr.id = sur.role_id where sr.is_deleted = 0 and sur.is_deleted = 0 and sr.level in (1,2,3,6)";
            userIds = pagination.find(sql, SysUserRole.class);
        }
        List<ProjectVisible> pvs = new ArrayList<>();
        for (SysUserRole sysUserRole : userIds) {
            ProjectVisible pv = new ProjectVisible();
            pv.setProjectId(projectInDb.getId());
            pv.setType(2);
            pv.setTid(sysUserRole.getUserId());
            pvs.add(pv);
        }
        projectVisibleRepository.save(pvs);

    }

    /**
     * 编辑概算保存项目
     */
    @Transactional(rollbackFor = RuntimeException.class)
    public Project estimateEditSave(Project project, Project projectInDb, EstimateBean estimateBean, Admin admin, ApproveStatusEnum approveStatusEnum) {
        Project p = projectService.editProject(project, projectInDb);
        p.setStatus(StatusEnum.ESTIMATE_ACCOUNTS.getStatus());
        p.setStatusDesc(StatusEnum.ESTIMATE_ACCOUNTS.getStatusDesc());
        p.setApproveStatusEstimate(approveStatusEnum.getApproveStatus());
        p = projectRepository.saveAndFlush(p);

        ProjectConfigBean projectConfigBeanConfig = sysConfigService.getProjectConfigBeanConfig();
        project.setProjectContributionProfitRateThreshold(projectConfigBeanConfig.getProjectContributionProfitRateThreshold());
        project.setUnderwrittenTaxRate(projectConfigBeanConfig.getUnderwrittenTaxRate());

        //清空重新保存概算信息
        clearEstimate(p);
        saveEstimate(p, estimateBean);
        return p;
    }
}
