package com.ruoyi.projetctCost.run;

import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.contractInfo.domain.ComContractInfoExchange;
import com.ruoyi.contractInfo.service.IComContractInfoExchangeService;
import com.ruoyi.contractInfo.contractInfoEnum.ContractInfoSjly;
import com.ruoyi.depart.departEnum.DepartType;
import com.ruoyi.depart.domain.SysDepart;
import com.ruoyi.depart.service.ISysDepartService;
import com.ruoyi.financeBudget.domain.FinanceBudget;
import com.ruoyi.financeBudget.service.IFinanceBudgetService;
import com.ruoyi.kyBg.domain.KyBgInfo;
import com.ruoyi.kyBg.service.IKyBgInfoService;
import com.ruoyi.kyTask.domain.KyTaskInfo;
import com.ruoyi.kyTask.service.IKyTaskInfoService;
import com.ruoyi.mesInfo.service.IMesInfoService;
import com.ruoyi.projectChbSwf.service.IKzksProjectChbSwfService;
import com.ruoyi.projectChbWxf.service.IKzksProjectChbWxfService;
import com.ruoyi.projectChbZyf.service.IKzksProjectChbZyfService;
import com.ruoyi.projectCost.domain.ProjectCost;
import com.ruoyi.projectCost.service.IProjectCostService;
import com.ruoyi.projetctCost.beenfactory.ServiceBeenFactory;
import com.ruoyi.wzCk.ckDetail.domain.WzOutboundOrderB;
import com.ruoyi.wzCk.ckDetail.service.IWzOutboundOrderBService;
import com.ruoyi.wzCk.ckInfo.domain.WzOutboundOrderH;
import com.ruoyi.wzCk.ckInfo.service.IWzOutboundOrderHService;
import org.apache.commons.lang3.ObjectUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;


public class projectCostSummaryRunnable implements Runnable {

    private final Integer i;
    private final ServiceBeenFactory serviceBeenFactory;
    private final RedisCache redisCache;

    public projectCostSummaryRunnable(Integer i, ServiceBeenFactory serviceBeenFactory, RedisCache redisCache) {
        this.i = i;
        this.serviceBeenFactory = serviceBeenFactory;
        this.redisCache = redisCache;
    }

    @Override
    public void run() {

        /*合同宽表service*/
        IComContractInfoExchangeService comContractInfoExchangeService = serviceBeenFactory.getComContractInfoExchangeService();
        /*科研报工service*/
        IKyBgInfoService kyBgInfoService = serviceBeenFactory.getKyBgInfoService();
        /*科研任务service*/
        IKyTaskInfoService kyTaskInfoService = serviceBeenFactory.getTaskInfoService();
        /*物资出库明细service*/
        IWzOutboundOrderBService ckDetail = serviceBeenFactory.getWzOutboundOrderBService();
        /*物资出库单service*/
        IWzOutboundOrderHService ckInfo = serviceBeenFactory.getWzOutboundOrderHService();
        /*事务费service*/
        IKzksProjectChbSwfService swfService = serviceBeenFactory.getProjectChbSwfService();
        /*外协费service*/
        IKzksProjectChbWxfService wxfService = serviceBeenFactory.getProjectChbWxfService();
        /*专用费service*/
        IKzksProjectChbZyfService zyfService = serviceBeenFactory.getProjectChbZyfService();
        /*部门service*/
        ISysDepartService departService = serviceBeenFactory.getDepartService();
        /*财务预算service*/
        IFinanceBudgetService financeBudgetService = serviceBeenFactory.getFinanceBudgetService();
        /*mes装机信息卡service*/
        IMesInfoService mesInfoService = serviceBeenFactory.getMesInfoService();
        /*项目成本service*/
        IProjectCostService projectCostService = serviceBeenFactory.getProjectCostService();

        final BigDecimal cpt = BigDecimal.valueOf(0); //值是0的固定比较值

        int beginOffset = 0;
        int size = 1000;
        if (i != 0) {
            beginOffset = i * 1000;
        }
        List<KyTaskInfo> taskList = kyTaskInfoService.selectKyTaskInfoListByRange(beginOffset, size);
        List<ProjectCost> projectCosts = new ArrayList<>();  //项目成本对象集合，for循环完之后批量插入数据

        for (KyTaskInfo kyTaskInfo : taskList) {
            ProjectCost projectCost;   //项目成本对象
            projectCost = new ProjectCost();
            projectCost.setId(null); //主键自增
            if (kyTaskInfo.getTaskno() != null) projectCost.setTaskno(kyTaskInfo.getTaskno());  //任务号
            if (kyTaskInfo.getTaskname() != null) projectCost.setTaskname(kyTaskInfo.getTaskname()); //任务名称
            if (kyTaskInfo.getXhname() != null) projectCost.setXhname(kyTaskInfo.getXhname()); //型号名称
            if (kyTaskInfo.getJhwcsj() != null) projectCost.setJhwcsj(kyTaskInfo.getJhwcsj()); //计划完成时间（进度要求）
            if (kyTaskInfo.getYzjdname() != null) projectCost.setYzjdname(kyTaskInfo.getYzjdname()); //研制阶段
            if (kyTaskInfo.getProcessPercent() != null)
                projectCost.setProcessPercent(BigDecimal.valueOf(Double.parseDouble(kyTaskInfo.getProcessPercent())).setScale(2, RoundingMode.HALF_UP)); //项目进度
            if (kyTaskInfo.getYzsl() != null) projectCost.setYzsl(kyTaskInfo.getYzsl()); //研制数量
            if (kyTaskInfo.getZrbm() != null) projectCost.setZrbm(kyTaskInfo.getZrbm()); //责任部门
            if (kyTaskInfo.getJycsid() != null) projectCost.setJycsid(Long.getLong(kyTaskInfo.getJycsid())); //下达部门ID
            if (kyTaskInfo.getJycs() != null) projectCost.setJycs(kyTaskInfo.getJycs()); //下达部门
            if (kyTaskInfo.getHxzxid() != null) projectCost.setHxzxid(kyTaskInfo.getHxzxid()); //1:横向 2:纵向
            if (kyTaskInfo.getHxzxname() != null) projectCost.setHxzxname(kyTaskInfo.getHxzxname()); //横向纵向
            if (kyTaskInfo.getTasktype() != null) projectCost.setTasktype(kyTaskInfo.getTasktype()); //任务类型
            if (kyTaskInfo.getAuditPrice() != null) projectCost.setAuditPrice(kyTaskInfo.getAuditPrice()); //审计审价
            if (kyTaskInfo.getIflag() != null) projectCost.setIflag(kyTaskInfo.getIflag()); //任务状态
            if (kyTaskInfo.getBrief() != null) projectCost.setBrief(kyTaskInfo.getBrief()); //用户简称
            if (kyTaskInfo.getRefTaskNo() != null)
                projectCost.setRefTaskNo(Long.getLong(kyTaskInfo.getRefTaskNo())); //父级任务号
            if (kyTaskInfo.getPccode() != null) projectCost.setPcCode(Long.getLong(kyTaskInfo.getPccode())); //批产任务号
            if (kyTaskInfo.getBlcode() != null) projectCost.setBlCode(Long.getLong(kyTaskInfo.getBlcode())); //备料任务号
            if (kyTaskInfo.getBusinessMan() != null) projectCost.setBusinessMan(kyTaskInfo.getBusinessMan()); //业务员



            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*合同额*/
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/

            List<ComContractInfoExchange> contractTask =
                    comContractInfoExchangeService.selectProjectCostFromCOmContractInfoExchangeByTaskNo(kyTaskInfo.getTaskno(), ContractInfoSjly.CONTRACT_TASK);

            BigDecimal htfpe = BigDecimal.valueOf(0); //初始化合同额,默认为0
            if (ObjectUtils.isNotEmpty(contractTask)) {
                for (ComContractInfoExchange comContractInfoExchange : contractTask)
                    if (comContractInfoExchange.getHtfpe() != null)
                        htfpe = htfpe.add(comContractInfoExchange.getHtfpe());
            }
            projectCost.setContractfpe(htfpe.setScale(2, RoundingMode.HALF_UP)); //合同额

            /* todo 根据签署日期（qsrq）计算每年的任务合同额 */

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*已收款*/
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/

            List<ComContractInfoExchange> contractPay =
                    comContractInfoExchangeService.selectProjectCostFromCOmContractInfoExchangeByTaskNo(kyTaskInfo.getTaskno(), ContractInfoSjly.CONTRACT_PAY);

            BigDecimal rwskje = BigDecimal.valueOf(0); //初始化已收款金额，默认为0
            if (ObjectUtils.isNotEmpty(contractPay)) {
                for (ComContractInfoExchange comContractInfoExchange : contractPay) {
                    if (comContractInfoExchange.getRwskje() != null)
                        rwskje = rwskje.add(comContractInfoExchange.getRwskje());
                }
            }
            projectCost.setTaskMoney(rwskje.setScale(2, RoundingMode.HALF_UP)); //已收款

            /* todo 根据到款日期/汇票到期日期（dkhpdqrq）计算每年的任务已收款*/

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/           /*材料费*/
            /*材料费*/
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/         /* 计算材料费，查询物资出库明细*/

            BigDecimal clfSum = BigDecimal.valueOf(0); //初始化材料费，默认为0

            /*根据任务号查询对应的出库单号集合*/
            List<WzOutboundOrderH> ckdhList = ckInfo.selectCkdhListFromCkinfoByTaskNo(kyTaskInfo.getTaskno());

            if (ckdhList != null) {
                for (WzOutboundOrderH wzOutboundOrderH : ckdhList) {
                    Integer count = ckDetail.getCkDetailDataCountByCkdh(wzOutboundOrderH.getCkdh());
                    /*经过跟沈工沟通，如果一个出库单对应的物料单超过5000，确认为异常数据，跳过计算*/
                    if (count > 5000) continue;

                    /*根据每个出库单号，查询物资出库明细中对应的物料单*/
                    List<WzOutboundOrderB> ckDetailDataList = ckDetail.selectProjectCostFromCkDetailByCkdh(wzOutboundOrderH.getCkdh());
                    /*循环每个物料单，求材料费*/
                    BigDecimal clf = BigDecimal.valueOf(0);
                    for (WzOutboundOrderB ckDetailData : ckDetailDataList) {
                        BigDecimal cgdj = ckDetailData.getCgdj(); //采购单价
                        BigDecimal nbdj = ckDetailData.getNbdj(); //内部单价
                        BigDecimal sfzsl = ckDetailData.getSfzsl(); //实发主数量

                        /*如果实发主数量为空，则给默认值0*/
                        Optional<BigDecimal> sfzsl1 = Optional.ofNullable(sfzsl);
                        sfzsl = sfzsl1.orElse(BigDecimal.valueOf(0));

                        /*计算：采购单价或内部单价*实发主数量 （若没有采购单价，则使用内部单价）*/
                        BigDecimal wlf = BigDecimal.valueOf(0);
                        if (cgdj != null) {
                            wlf = cgdj.multiply(sfzsl);
                        } else if (nbdj != null) {
                            wlf = nbdj.multiply(sfzsl);
                        }
                        clf = clf.add(wlf);
                    }
                    clfSum = clfSum.add(clf);
                }
            }

            projectCost.setClf(clfSum.setScale(2, RoundingMode.HALF_UP)); //材料费

            /* todo 根据制单日期（zdrq）计算每年的任务材料费*/

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*事务费*///同任务号的事务费数据，辅助金额累加
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            BigDecimal swf = swfService.selectSwfByTaskno(kyTaskInfo.getTaskno());
            BigDecimal swfSum = Optional.ofNullable(swf).orElse(BigDecimal.valueOf(0));
            projectCost.setSwf(swfSum.setScale(2, RoundingMode.HALF_UP)); //事务费

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*外协费*///同任务号的外协费数据，辅助金额累加
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            BigDecimal wxf = wxfService.selectWxfByTaskno(kyTaskInfo.getTaskno());
            BigDecimal wxfSum = Optional.ofNullable(wxf).orElse(BigDecimal.valueOf(0));
            projectCost.setWxf(wxfSum.setScale(2, RoundingMode.HALF_UP)); //外协费

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*专用费*///同任务号的专用费数据，辅助金额累加
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            BigDecimal zyf = zyfService.selectZyfByTaskno(kyTaskInfo.getTaskno());
            BigDecimal zyfSum = Optional.ofNullable(zyf).orElse(BigDecimal.valueOf(0));
            projectCost.setZyf(zyfSum.setScale(2, RoundingMode.HALF_UP)); //专用费

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*设计工时，生产工时，总工时*///和任务号关联得类型为设计部门的科研报工工时累加
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/

            List<KyBgInfo> kyBgInfoList = kyBgInfoService.selectKyBgInfoListByTaskno(kyTaskInfo.getTaskno());
            BigDecimal sjgs = BigDecimal.valueOf(0); //初始化设计工时，默认为0
            BigDecimal scgs = BigDecimal.valueOf(0); //初始化生产工时，默认为0
            if (kyBgInfoList != null) {
                for (KyBgInfo kyBgInfo : kyBgInfoList) {
                    SysDepart sysDepart = departService.selectDeptTypeByDeptName(kyBgInfo.getUserdept());
                    if (sysDepart != null) {
                        if (Objects.equals(sysDepart.getDeptType(), DepartType.DESIGN_TIME)) {
                            BigDecimal workhour = kyBgInfo.getWorkhour();
                            BigDecimal bigDecimal = Optional.ofNullable(workhour).orElse(BigDecimal.valueOf(0));
                            sjgs = sjgs.add(bigDecimal);
                        } else if (Objects.equals(sysDepart.getDeptType(), DepartType.PRODUCE_TIME)) {
                            BigDecimal workhour = kyBgInfo.getWorkhour();
                            BigDecimal bigDecimal = Optional.ofNullable(workhour).orElse(BigDecimal.valueOf(0));
                            scgs = scgs.add(bigDecimal);
                        }
                    }
                }
            }
            projectCost.setSjgs(sjgs.setScale(2, RoundingMode.HALF_UP)); //设计工时
            projectCost.setScgs(scgs.setScale(2, RoundingMode.HALF_UP)); //生产工时
            projectCost.setWorkhour(sjgs.add(scgs)); //总工时

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*燃动费*///前：直接成本*1.5% 后：(设计工时+生产工时)*6.78 备：直接成本：(材料费+事务费+外协费+专用费)
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*固资费*///前：直接成本*2.5% 后：(设计工时+生产工时)*15.97 备：直接成本：(材料费+事务费+外协费+专用费)
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*工资费*///前：直接成本*17% 后：设计工时*211.25+生产工时*130 备：直接成本：(材料费+事务费+外协费+专用费)
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*管理费*///前：直接成本*5%
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/

            BigDecimal directCosts = clfSum.add(swfSum).add(wxfSum).add(zyfSum); //直接成本

            BigDecimal rdfSum; //燃动费
            BigDecimal gzzjSum; // 固定资产折旧费
            BigDecimal gzfSum; //工资费
            BigDecimal glfSum = BigDecimal.valueOf(0); //管理费，默认为0
            if (!(sjgs.compareTo(cpt) == 0) || !(scgs.compareTo(cpt) == 0)) { //如果设计工时或者生产工时有一个不为0，则根据后方法计算
                BigDecimal gsSum = sjgs.add(scgs); //工时总和
                rdfSum = gsSum.multiply(BigDecimal.valueOf(6.78)); //求燃动费
                gzzjSum = gsSum.multiply(BigDecimal.valueOf(15.97)); //求固资费
                //求工资费
                BigDecimal sjgz = sjgs.multiply(BigDecimal.valueOf(211.25));//设计工资
                BigDecimal scgz = scgs.multiply(BigDecimal.valueOf(130)); //生产工资
                gzfSum = sjgz.add(scgz); //工资费
            } else {
                rdfSum = directCosts.multiply(BigDecimal.valueOf(0.015)); //求燃动费
                gzzjSum = directCosts.multiply(BigDecimal.valueOf(0.025)); //求固资费
                gzfSum = directCosts.multiply(BigDecimal.valueOf(0.17)); //求工资费
                glfSum = directCosts.multiply(BigDecimal.valueOf(0.05)); //求管理费
            }
            projectCost.setRldlf(rdfSum.setScale(2, RoundingMode.HALF_UP)); //设置燃料动力费
            projectCost.setGdzczj(gzzjSum.setScale(2, RoundingMode.HALF_UP)); //设置固定资产折旧费
            projectCost.setGzjlwf(gzfSum.setScale(2, RoundingMode.HALF_UP)); //设置工资费
            projectCost.setGlf(glfSum.setScale(2, RoundingMode.HALF_UP)); //设置管理费

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*总成本*///材料费+事务费+外协费+专用费+燃动费+固资费+工资+管理费
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            BigDecimal zcb = clfSum.add(swfSum).add(wxfSum).add(zyfSum).add(rdfSum).add(gzzjSum).add(gzfSum).add(glfSum); //求总成本
            projectCost.setZcb(zcb.setScale(2, RoundingMode.HALF_UP)); //设置总成本

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*预估价*///科研平台财务预算的预估价，根据科研任务号查找
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            FinanceBudget financeBudget = financeBudgetService.selectEstimationCoatByTaskno(kyTaskInfo.getTaskno());
            String estimationCoat = financeBudget.getEstimationCoat();
            BigDecimal ygj = BigDecimal.valueOf(0);
            if (ObjectUtils.isNotEmpty(estimationCoat)) {
                ygj = BigDecimal.valueOf(Double.parseDouble(estimationCoat));
            }
            projectCost.setEstimationCoat(ygj.setScale(2, RoundingMode.HALF_UP)); //设置预估价

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*利润额*///合同额或预估价-总成本，优先合同额
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*利润率*///利润额 /（合同额或预估价）
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/

            BigDecimal lre = BigDecimal.valueOf(0); //初始化利润额，默认为0
            BigDecimal lrl = BigDecimal.valueOf(0); //利润率
            if (!(htfpe.compareTo(lre) == 0)) { //有合同额，优先合同额-总成本
                lre = htfpe.subtract(zcb);
                lrl = lre.divide(htfpe, 2, RoundingMode.HALF_UP); //避免除不尽，设置保留两位小数
            } else if (!(ygj.compareTo(lre) == 0)) {
                lre = ygj.subtract(zcb);
                lrl = lre.divide(ygj, 2, RoundingMode.HALF_UP); //避免除不尽，设置保留两位小数
            }
            projectCost.setLre(lre.setScale(2, RoundingMode.HALF_UP)); //设置利润额
            projectCost.setLrl(lrl.setScale(2, RoundingMode.HALF_UP)); //设置利润率

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*单台收入*///（合同额或预估价）/数量 有合同额，优先合同额
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/

            BigDecimal dtsr = BigDecimal.valueOf(0); //初始化单台收入，默认为0
            if (!(htfpe.compareTo(lre) == 0)) {
                dtsr = htfpe.divide(BigDecimal.valueOf(kyTaskInfo.getYzsl()), 2, RoundingMode.HALF_UP); //避免除不尽，设置保留两位小数
            } else if (!(ygj.compareTo(lre) == 0)) {
                dtsr = ygj.divide(BigDecimal.valueOf(kyTaskInfo.getYzsl()), 2, RoundingMode.HALF_UP); //避免除不尽，设置保留两位小数
            }
            projectCost.setOneIncome(dtsr.setScale(2, RoundingMode.HALF_UP)); //设置单台收入

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*单台成本*///（总成本/数量）
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/

            BigDecimal dtcb = zcb.divide(BigDecimal.valueOf(kyTaskInfo.getYzsl()), 2, RoundingMode.HALF_UP); //避免除不尽，设置保留两位小数
            projectCost.setOneCost(dtcb);

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*单台利润*/// 单台收入-单台成本
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/

            BigDecimal dtlr = dtsr.subtract(dtcb);
            projectCost.setOneProfit(dtlr.setScale(2, RoundingMode.HALF_UP));  //设置单台利润

            /*------------------------------------------------------------------------------------------------------------------------------------------------*/
            /*成本进度*/// 总成本/（合同额或预估价）
            /*------------------------------------------------------------------------------------------------------------------------------------------------*/

            BigDecimal cbjd = BigDecimal.valueOf(0);
            if (!(htfpe.compareTo(lre) == 0)) { //有合同额，优先合同额-总成本
                cbjd = zcb.divide(htfpe, 2, RoundingMode.HALF_UP); //避免除不尽，设置保留两位小数
            } else if ((!(ygj.compareTo(lre) == 0))) {
                cbjd = zcb.divide(ygj, 2, RoundingMode.HALF_UP); //避免除不尽，设置保留两位小数
            }
            projectCost.setCostPercent(cbjd.setScale(2,RoundingMode.HALF_UP)); //设置成本进度

            projectCosts.add(projectCost);
        }
        boolean flag = projectCostService.insertBatchProjectCost(projectCosts);
    }
}