package com.sifang.modules.changes.service;

import com.google.gson.Gson;
import com.jfinal.plugin.activerecord.Record;
import com.sifang.modules.changes.constant.CustomerEntryChangeDesignConstant;
import com.sifang.modules.changes.dao.CrmCustomerEntryChangeDesignDetailDao;
import com.sifang.modules.changes.dao.CustomerEntryChangeDesignComponentDao;
import com.sifang.modules.changes.dao.CustomerEntryChangeDesignDao;
import com.sifang.modules.changes.dao.CustomerEntryChangeRecordDao;
import com.sifang.modules.changes.entity.CrmCustomerEntryChangeDesign;
import com.sifang.modules.changes.entity.CrmCustomerEntryChangeDesignComponent;
import com.sifang.modules.changes.entity.CrmCustomerEntryChangeDesignDetail;
import com.sifang.modules.changes.vo.AddDesignChangeComponentReq;
import com.sifang.modules.changes.vo.AddDesignChangeReq;
import com.sifang.modules.changes.vo.DesignChangeAuditReq;
import com.sifang.modules.changes.vo.DesignChangeAuditVo;
import com.sifang.modules.customer.Service.*;
import com.sifang.modules.customer.constant.CustomerEntryConstants;
import com.sifang.modules.customer.constant.PartnerConstants;
import com.sifang.modules.customer.constant.SourceConstants;
import com.sifang.modules.customer.dao.CrmCustomerIncomingApplicationDao;
import com.sifang.modules.customer.dao.CustomerEntryDao;
import com.sifang.modules.customer.entity.CrmCustomerIncomingApplication;
import com.sifang.modules.customer.entity.CustomerEntry;
import com.sifang.modules.customer.form.QueryDocumentRes;
import com.sifang.modules.flowable.constants.ItemConstants;
import com.sifang.modules.flowable.dao.ItemManageDao;
import com.sifang.modules.flowable.dao.ItemTaskDetailDao;
import com.sifang.modules.flowable.entity.ItemManage;
import com.sifang.modules.flowable.utils.FormUtils;
import com.sifang.modules.platform.utils.PlantformUtils;
import com.sifang.modules.setting.constant.ProcessSetConstants;
import com.sifang.modules.sunshine.SystemSetting.dao.PlanMaterialEntryDao;
import com.sifang.modules.sunshine.SystemSetting.utils.BusinessException;
import com.sifang.modules.sunshine.SystemSetting.utils.Result;
import com.sifang.modules.sunshine.SystemSetting.utils.StringUtil;
import com.sifang.modules.supply.stock.dao.SupplyMaterialDao;
import com.sifang.modules.sys.common.UserUtils;
import com.sifang.modules.sys.common.entity.User;
import com.sifang.modules.sys.common.utils.DateUtils;
import com.sifang.modules.sys.entity.Operator;
import com.sifang.modules.sys.util.*;
import com.sifang.modules.taskdispatch.dao.CrmReviewDispatchDao;
import com.sifang.modules.taskdispatch.service.CrmPriorReviewSettingService;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.SQLQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.sifang.modules.changes.constant.CustomerEntryChangeDesignConstant.AUDIT_STATUS_PASS;
import static com.sifang.modules.changes.constant.CustomerEntryChangeDesignConstant.AUDIT_STATUS_REJECT;

@Service
public class CustomerEntryChangeDesignService {

    @Autowired
    CustomerEntryChangeDesignDao customerEntryChangeDesignDao;
    @Autowired
    CustomerEntryDao entryDao;
    @Autowired
    CustomerEntryChangeDesignComponentDao customerEntryChangeDesignComponentDao;
    @Autowired
    CustomerEntryService entryService;
    @Autowired
    CustomerEntryMsgService entryMsgService;

    @Autowired
    private ItemManageDao itemManageDao;
    @Autowired
    private CrmReviewDispatchDao reviewDispatchDao;
    @Autowired
    private PlanMaterialEntryDao planMaterialEntryDao;
    @Autowired
    private CustomerEntryComponentService customerEntryComponentService;
    @Autowired
    private ItemTaskDetailDao itemTaskDetailDao;
    @Autowired
    private SupplyMaterialDao supplyMaterialDao;
    @Autowired
    @Lazy
    private GuangFaManagemnetService guangFaManagemnetService;
    @Autowired
    private CrmCustomerIncomingApplicationDao applicationDao;
    @Autowired
    YueXiuProjectOperatingService yueXiuProjectOperatingService;
    @Autowired
    YueXiuContractService yueXiuContractService;
    @Autowired
    private OperatingLeaseService operatingLeaseService;
    @Autowired
    private HuaRongContractService huaRongContractService;
    @Autowired
    private CustomerEntryChangeRecordDao customerEntryChangeRecordDao;
    @Autowired
    private CrmCustomerEntryChangeDesignDetailDao changeDesignDetailDao;

    @Autowired
    private CrmPriorReviewSettingService crmPriorReviewSettingService;
    public void listData(LayuiPage<Record> page, Map<String, String> params, Operator operator) {
        customerEntryChangeDesignDao.selectList(page, params, operator);
    }

    public CrmCustomerEntryChangeDesign get(String id) {
        return customerEntryChangeDesignDao.get(id);
    }

    public static boolean validStatus(String status) {
        // 设计变更申请 电站状态要在待安装时才可提交
        return StringUtils.equalsAny(status, CustomerEntryConstants.ENTRY_STATUS_DAZ);
    }

    public static String invalidStatusMsg() {
        return "只有待安装的电站才可以变更设计！";
    }

    @Transactional(rollbackFor = Exception.class)
    public Result addChangeDesign(AddDesignChangeReq req) {
        CrmCustomerEntryChangeDesign change = new CrmCustomerEntryChangeDesign();
        CustomerEntry entry = entryDao.get(req.getEntryId());

        String checkApplyResult = CrmUtils.checkExistApply(entry.getStatus(), entry.getId());
        if (StringUtil.isNotBlank(checkApplyResult)) {
            return Result.fail(checkApplyResult);
        }
        if (customerEntryChangeRecordDao.getIfHaveDesignChange(entry.getId()) > 0) {
            return Result.fail("该电站有待资方审核的变更记录，请审核后再提交");
        }

//        if (!validStatus(entry.getStatus())) {
//            return Result.fail(invalidStatusMsg());
//        }

        change.setNumber(PlantformUtils.getOrderNumber());
        change.setEntryId(req.getEntryId());
        change.setPowerStationCode(entry.getPowerStationCode());
        change.setNum((int) (customerEntryChangeDesignDao.existsNum(entry.getId()) + 1));
        change.setDesignDrawings(req.getDzDoc());
        change.setPreDesignDrawings(req.getPreDzDoc());
        change.setSchemeType(req.getSchemeType());
        change.setPreSchemeType(req.getPreSchemeType());
        change.setSchemeTypeId(req.getSchemeTypeId());
        change.setPreSchemeTypeId(req.getPreSchemeTypeId());
        change.setSchemeTypeName(req.getSchemeTypeName());
        change.setPreSchemeTypeName(req.getPreSchemeTypeName());
        change.setSchemeId(req.getSchemeId());
        change.setPreSchemeId(req.getPreSchemeId());
        change.setSchemeName(req.getSchemeName());
        change.setPreSchemeName(req.getPreSchemeName());
        change.setStatus(CustomerEntryChangeDesignConstant.AUDIT_STATUS_WAIT);
        change.setReason(req.getReason());
        change.setZjpbImg(req.getZjpbImgDoc());
        change.setZjzxImg(req.getZjzxImgDoc());
        change.setZjcsImg(req.getZjcsImgDoc());
        change.setZjhsImg(req.getZjhsImgDoc());
        change.setPreZjpbImg(req.getPreZjpbImgDoc());
        change.setPreZjzxImg(req.getPreZjzxImgDoc());
        change.setPreZjcsImg(req.getPreZjcsImgDoc());
        change.setPreZjhsImg(req.getPreZjhsImgDoc());
        User user = UserUtils.getUser();
        change.setCreator(CrmUtils.getUserXM(user));
        change.setCreateBy(user.getId());
        change.setCreateTime(new Date());
        change.setAuditBy(null);
        change.setAuditor(null);
        change.setAuditTime(null);
        change.setAuditRemark(null);
        //清空设计变更备注
        change.setAuditRemark("");
        customerEntryChangeDesignDao.save(change);

        List<AddDesignChangeComponentReq> components = mergeComponentReqs(req.getComponents());
        //逆变器 判断不同规格下的逆变器是否有相同品牌的
        List<AddDesignChangeComponentReq> nbqList = components.stream().filter(v -> "1".equals(v.getType()) && "1".equals(v.getFlag())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(nbqList) && nbqList.size() > 1) {
            //获取所有逆变器的规格
            List<String> specList = nbqList.stream().map(r -> r.getSpec()).collect(Collectors.toList());
            List<List<String>> lists = new ArrayList<>();
            for (String spec : specList) {
                //获取该规格下所有品牌
                List<Record> brandList = supplyMaterialDao.findBrandBySpec(spec, "1");
                List<String> list = brandList.stream().map(r -> r.getStr("material_brand")).collect(Collectors.toList());
                lists.add(list);
            }
            //判断是否有相同品牌的逆变器
            boolean flag = CrmUtils.containsCommonString(lists);
            if (!flag){
                throw new BusinessException(StringUtil.join(specList,",")+"规格下没有相同品牌的逆变器");
            }
        }
        // 查询使用的物料
        List<Record> usedZJList = planMaterialEntryDao.findUsedByEntryId(entry.getId(), "组件");
        List<Record> usedNBQList = planMaterialEntryDao.findUsedByEntryId(entry.getId(), "逆变器");
        String zjIdO = "";
        String zjIdN = "";
        Integer zjNumN = 0;
        String zjSpecO = "";
        String zjSpecN = "";
        List<String> nbqListO = new ArrayList<>();
        List<String> nbqListN = new ArrayList<>();
        for (AddDesignChangeComponentReq componentReq : components) {
            CrmCustomerEntryChangeDesignComponent component = componentFromReq(componentReq, change.getId(), user,req.getProjectId());
            if ("1".equals(component.getItemType())) {
                if (component.getFlag().equals("0")) {
                    nbqListO.add(component.getModel()+component.getNum());
                }
                else {
                    nbqListN.add(component.getModel()+component.getNum());
                }
            }
            else if ("3".equals(component.getItemType())) {
                if (component.getFlag().equals("0")) {
                    zjIdO = component.getItemId();
                    zjSpecO = component.getModel();
                }
                else {
                    zjIdN = component.getItemId();
                    zjNumN = component.getNum();
                    zjSpecN = component.getModel();
                }
            }
            customerEntryChangeDesignComponentDao.save(component);
        }
        if (!usedNBQList.isEmpty()) {
            // 使用了逆变器 则不能修改逆变器
            if (!checkListEquals(nbqListO, nbqListN)) {
                throw new BusinessException("已经扫码使用逆变器，需要删除物料才能变更");
            }
        }

        if (!usedZJList.isEmpty()) {
            // 使用了组件 则不能修改/减少组件  只能增加
            if (!checkZjEqual(zjIdO,zjSpecO,zjIdN,zjSpecN,entry.getPartnerId())) {
                throw new BusinessException("已经扫码使用组件，需要删除物料才能变更");
            }
            if (usedZJList.size() > zjNumN) {
                throw new BusinessException("已经扫码使用组件，需要删除物料才能变更");
            }
        }

        entryMsgService.saveCustomerEntryMsg(Operator.of(user), entry.getId(), CustomerEntryConstants.ENTRY_ADD_CHANGE
                , String.format("第%d次提交电站设计变更申请", change.getNum()), null);

        //所有的变更审核 要走待办事项审批流程，默认审批人为原审核人员  设计变更审核 查询的是设计审核/设计变更审核人；
        ItemManage itemManage = itemManageDao.addItemChange(FormUtils.ENTRY_CHANGE_SJBG, entry.getId(),change.getId(),"设计信息变更(" + entry.getTenantName() + "-" + entry.getPowerStationCode() + ")-" + DateUtils.formatDate(change.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), change.getCreateTime(), user.getUserName());
        //获取最近一次 设计审核/设计变更审核人
        String userId = itemManageDao.getLastAuditUserId("91,97", entry.getId());
        if (StringUtil.isNotBlank(userId)) {
//            itemManage.setAssignAuditUserId(userId);
            itemManage.setPreferUserId(userId);
        }
        itemManageDao.save(itemManage);
        //大代理商优先审核
        String groupName = "设计审核";
        crmPriorReviewSettingService.traderPriorityReview(entry.getCreateTraderId(),itemManage.getId(),groupName);
        return Result.ok();
    }

    @Transactional(rollbackFor = Exception.class)
    public Result addChangeDesignHR(List<AddDesignChangeReq> reqList) {
        User user = UserUtils.getUser();
        String entryId = reqList.get(0).getEntryId();
        String reason = reqList.get(0).getReason();
        String schemeType = reqList.get(0).getSchemeType();
        CustomerEntry  entry = entryDao.get(entryId);

        String checkApplyResult = CrmUtils.checkExistApply(entry.getStatus(), entry.getId());
        if (StringUtil.isNotBlank(checkApplyResult)) {
            return Result.fail(checkApplyResult);
        }
        if (customerEntryChangeRecordDao.getIfHaveDesignChange(entry.getId()) > 0) {
            return Result.fail("该电站有待资方审核的变更记录，请审核后再提交");
        }


        CrmCustomerEntryChangeDesign change = new CrmCustomerEntryChangeDesign();
        String orderNumber = PlantformUtils.getOrderNumber();
        change.setNumber(orderNumber);
        change.setEntryId(entryId);
        change.setPowerStationCode(entry.getPowerStationCode());
        change.setNum((int) (customerEntryChangeDesignDao.existsNum(entry.getId()) + 1));
        change.setStatus(CustomerEntryChangeDesignConstant.AUDIT_STATUS_WAIT);
        change.setSchemeType(schemeType);
        change.setReason(reason);
        change.setCreator(CrmUtils.getUserXM(user));
        change.setCreateBy(user.getId());
        change.setCreateTime(new Date());
        change.setAuditBy(null);
        change.setAuditor(null);
        change.setAuditTime(null);
        change.setAuditRemark(null);
        //清空设计变更备注
        change.setAuditRemark("");
        customerEntryChangeDesignDao.save(change);

        for (AddDesignChangeReq req : reqList) {
            CrmCustomerEntryChangeDesignDetail changeDetail = new CrmCustomerEntryChangeDesignDetail();
            changeDetail.setNumber(orderNumber);
            changeDetail.setEntryId(entryId);
            changeDetail.setPowerStationCode(entry.getPowerStationCode());
            changeDetail.setProjectId(req.getProjectId());
            changeDetail.setDesignDrawings(req.getDzDoc());
            changeDetail.setPreDesignDrawings(req.getPreDzDoc());
            changeDetail.setSchemeType(req.getSchemeType());
            changeDetail.setPreSchemeType(req.getPreSchemeType());
            changeDetail.setSchemeTypeId(req.getSchemeTypeId());
            changeDetail.setPreSchemeTypeId(req.getPreSchemeTypeId());
            changeDetail.setSchemeTypeName(req.getSchemeTypeName());
            changeDetail.setPreSchemeTypeName(req.getPreSchemeTypeName());
            changeDetail.setSchemeId(req.getSchemeId());
            changeDetail.setPreSchemeId(req.getPreSchemeId());
            changeDetail.setSchemeName(req.getSchemeName());
            changeDetail.setPreSchemeName(req.getPreSchemeName());
            changeDetail.setZjpbImg(req.getZjpbImgDoc());
            changeDetail.setZjzxImg(req.getZjzxImgDoc());
            changeDetail.setZjcsImg(req.getZjcsImgDoc());
            changeDetail.setZjhsImg(req.getZjhsImgDoc());
            changeDetail.setPreZjpbImg(req.getPreZjpbImgDoc());
            changeDetail.setPreZjzxImg(req.getPreZjzxImgDoc());
            changeDetail.setPreZjcsImg(req.getPreZjcsImgDoc());
            changeDetail.setPreZjhsImg(req.getPreZjhsImgDoc());
            changeDetail.setCreator(CrmUtils.getUserXM(user));
            changeDetail.setCreateBy(user.getId());
            changeDetail.setCreateTime(new Date());
            changeDesignDetailDao.save(changeDetail);

            List<AddDesignChangeComponentReq> components = mergeComponentReqs(req.getComponents());
            //逆变器 判断不同规格下的逆变器是否有相同品牌的
            List<AddDesignChangeComponentReq> nbqList = components.stream().filter(v -> "1".equals(v.getType()) && "1".equals(v.getFlag())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(nbqList) && nbqList.size() > 1) {
                //获取所有逆变器的规格
                List<String> specList = nbqList.stream().map(r -> r.getSpec()).collect(Collectors.toList());
                List<List<String>> lists = new ArrayList<>();
                for (String spec : specList) {
                    //获取该规格下所有品牌
                    List<Record> brandList = supplyMaterialDao.findBrandBySpec(spec, "1");
                    List<String> list = brandList.stream().map(r -> r.getStr("material_brand")).collect(Collectors.toList());
                    lists.add(list);
                }
                //判断是否有相同品牌的逆变器
                boolean flag = CrmUtils.containsCommonString(lists);
                if (!flag){
                    throw new BusinessException(StringUtil.join(specList,",")+"规格下没有相同品牌的逆变器");
                }
            }
            // 查询使用的物料
            List<Record> usedZJList = planMaterialEntryDao.findUsedByEntryId(entry.getId(), "组件");
            List<Record> usedNBQList = planMaterialEntryDao.findUsedByEntryId(entry.getId(), "逆变器");
            String zjIdO = "";
            String zjIdN = "";
            Integer zjNumN = 0;
            String zjSpecO = "";
            String zjSpecN = "";
            List<String> nbqListO = new ArrayList<>();
            List<String> nbqListN = new ArrayList<>();
            for (AddDesignChangeComponentReq componentReq : components) {
                CrmCustomerEntryChangeDesignComponent component = componentFromReq(componentReq, change.getId(), user,req.getProjectId());
                if ("1".equals(component.getItemType())) {
                    if (component.getFlag().equals("0")) {
                        nbqListO.add(component.getModel()+component.getNum());
                    }
                    else {
                        nbqListN.add(component.getModel()+component.getNum());
                    }
                }
                else if ("3".equals(component.getItemType())) {
                    if (component.getFlag().equals("0")) {
                        zjIdO = component.getItemId();
                        zjSpecO = component.getModel();
                    }
                    else {
                        zjIdN = component.getItemId();
                        zjNumN = component.getNum();
                        zjSpecN = component.getModel();
                    }
                }
                customerEntryChangeDesignComponentDao.save(component);
            }
            if (!usedNBQList.isEmpty()) {
                // 使用了逆变器 则不能修改逆变器
                if (!checkListEquals(nbqListO, nbqListN)) {
                    throw new BusinessException("已经扫码使用逆变器，需要删除物料才能变更");
                }
            }

            if (!usedZJList.isEmpty()) {
                // 使用了组件 则不能修改/减少组件  只能增加
                if (!checkZjEqual(zjIdO,zjSpecO,zjIdN,zjSpecN,entry.getPartnerId())) {
                    throw new BusinessException("已经扫码使用组件，需要删除物料才能变更");
                }
                if (usedZJList.size() > zjNumN) {
                    throw new BusinessException("已经扫码使用组件，需要删除物料才能变更");
                }
            }
        }
        entryMsgService.saveCustomerEntryMsg(Operator.of(user), entry.getId(), CustomerEntryConstants.ENTRY_ADD_CHANGE
                , String.format("第%d次提交电站设计变更申请", change.getNum()), null);

        //所有的变更审核 要走待办事项审批流程，默认审批人为原审核人员  设计变更审核 查询的是设计审核/设计变更审核人；
        ItemManage itemManage = itemManageDao.addItemChange(FormUtils.ENTRY_CHANGE_SJBG, entry.getId(),change.getId(),"设计信息变更(" + entry.getTenantName() + "-" + entry.getPowerStationCode() + ")-" + DateUtils.formatDate(change.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), change.getCreateTime(), user.getUserName());
        //获取最近一次 设计审核/设计变更审核人
        String userId = itemManageDao.getLastAuditUserId("91,97", entry.getId());
        if (StringUtil.isNotBlank(userId)) {
//            itemManage.setAssignAuditUserId(userId);
            itemManage.setPreferUserId(userId);
        }
        itemManageDao.save(itemManage);
        //大代理商优先审核
        String groupName = "设计审核";
        crmPriorReviewSettingService.traderPriorityReview(entry.getCreateTraderId(),itemManage.getId(),groupName);
        return Result.ok();
    }

    /**
     * 校验 后者包含前者
     * @return true表示包含 ，false表示不包含
     */
    public boolean checkListEquals(List<String> listO, List<String> listW) {
        if (listO.size() > listW.size()) {
            return false;
        }
        if (!listW.containsAll(listO)) {
            return false;
        }
        return true;
    }

    /**
     * 校验 后者包含前者
     * @return true表示包含 ，false表示不包含
     */
    public boolean checkMapEquals(List<String> listO, List<String> listW) {
        if (listO.size() > listW.size()) {
            return false;
        }
        if (!listW.containsAll(listO)) {
            return false;
        }
        return true;
    }

    private List<AddDesignChangeComponentReq> mergeComponentReqs(List<AddDesignChangeComponentReq> components) {
        List<AddDesignChangeComponentReq> ret = new ArrayList<>();
        Map<String, AddDesignChangeComponentReq> map = new HashMap<>();
        for (AddDesignChangeComponentReq component : components) {
            if (Objects.equals("0", component.getFlag())) {
                ret.add(component);
            } else {
                AddDesignChangeComponentReq req = map.get(component.getItemId());
                if (req == null) {
                    ret.add(component);
                    map.put(component.getItemId(), component);
                } else {
                    req.setNum(req.getNum() + component.getNum());
                }
            }
        }
        return ret;
    }

    private boolean hasWaitingAuditChangeDesign(String entryId) {
        return customerEntryChangeDesignDao.findByEntryIdAndStatus(entryId, CustomerEntryChangeDesignConstant.AUDIT_STATUS_WAIT) != null;
    }

    @Transactional(rollbackFor = Exception.class)
    public Result tempDesignChange(DesignChangeAuditReq req) {
        String changeId = req.getChangeId();
        CrmCustomerEntryChangeDesign design = customerEntryChangeDesignDao.get(changeId);
        design.setAuditRemark(req.getMsg());
        customerEntryChangeDesignDao.save(design);
        return Result.ok();
    }

    @Transactional(rollbackFor = Exception.class)
    public Result auditDesignChange(DesignChangeAuditReq req) {
        String changeId = req.getChangeId();
        CrmCustomerEntryChangeDesign design = customerEntryChangeDesignDao.get(changeId);
        CustomerEntry entry = entryDao.get(design.getEntryId());
        Integer designCapacity = entry.getDesignCapacity();
//        if (!validStatus(entry.getStatus())) {
//            return Result.fail(invalidStatusMsg());
//        }

        boolean pass = Objects.equals(req.getValue(), AUDIT_STATUS_PASS);
        GuardUtils.in(new String[]{AUDIT_STATUS_PASS, AUDIT_STATUS_REJECT}, req.getValue(), "审核状态不合法！");
        User user = UserUtils.getUser();
        DesignChangeAuditVo vo = new DesignChangeAuditVo();
        vo.setMsg(req.getMsg());
        vo.setChangeId(changeId);
        vo.setValue(req.getValue());
        vo.setUserId(user.getId());
        vo.setUserName(CrmUtils.getUserXM(user.getId()));
        int affected = customerEntryChangeDesignComponentDao.audit(vo);
        if (affected < 1) {
            return Result.fail("申请记录已经审核完成，请刷新页面！");
        }
        List<Record> components = customerEntryChangeDesignComponentDao.findByDesignId(design.getId());
        List<Record> postComponents = components.stream().filter(e -> Objects.equals(e.getStr("flag"), "1")).collect(Collectors.toList());
        //变化后的设计容量
        int updateCapacity = 0;
        String model = "";
        List<Record> postZjRecord=new ArrayList<>(); //组件变更的信息
        for (Record postComponent : postComponents) {
            if (Objects.equals(postComponent.getStr("item_type"), "3")) {
                postZjRecord.add(postComponent);
                updateCapacity += postComponent.getInt("num") * Integer.parseInt(postComponent.getStr("model"));
                model = postComponent.getStr("model");
            }
        }
        if (Objects.equals(req.getValue(), "1")) {
            // 电站信息同步
            entryService.designChange(design, postComponents, model, updateCapacity, entry.getReceivingReportId());
            entry.setDesignDrawings(design.getDesignDrawings());
            entry.setSchemeType(design.getSchemeType());
            entry.setSchemeTypeId(design.getSchemeTypeId());
            entry.setSchemeTypeName(design.getSchemeTypeName());
            entry.setSchemeId(design.getSchemeId());
            entry.setSchemeName(design.getSchemeName());
            entry.setComponentSpec(model);
            entry.setDesignCapacity(updateCapacity);
            entry.setZjcsImg(design.getZjcsImg());
            entry.setZjhsImg(design.getZjhsImg());
            entry.setZjpbImg(design.getZjpbImg());
            entry.setZjzxImg(design.getZjzxImg());
        }
        String msg = (StringUtil.isNotBlank(req.getMsg()) ? ","+ req.getMsg() : "");
        String content = String.format("第%d次电站设计变更申请，审核" + (pass ? "通过" : "驳回") + msg, design.getNum());
        entryMsgService.saveCustomerEntryMsg(Operator.of(user), entry.getId(),
                (pass ? CustomerEntryConstants.ENTRY_CHANGE_PASS : CustomerEntryConstants.ENTRY_CHANGE_REFUSE), content, null);
        CrmCustomerIncomingApplication application = applicationDao.getByEntryId(entry.getId());

        if(FormSetUtils.processSetEnable(entry.getPartnerId(), ProcessSetConstants.NODE_KEY_NAME_ZFSH)) {
            List<Record> preComponents = components.stream().filter(e -> Objects.equals(e.getStr("flag"), "0")).collect(Collectors.toList());
            String preModel = "";//变更前的组件规格
            for (Record preComponent : preComponents) {
                if (Objects.equals(preComponent.getStr("item_type"), "3")) {
                    preModel = preComponent.getStr("model");
                    break;
                }
            }

            if (req.getValue().equals("1")) {
                switch (entry.getPartnerId()) {
                    case PartnerConstants.PARTNER_ID_YX:
                        if (updateCapacity!=designCapacity  || !model.equals(preModel)) {
                            //处于 待安装 待安装验收 安装验收退回 安装自审
                            if (StringUtil.equalsAny(entry.getStatus(), CustomerEntryConstants.ENTRY_STATUS_DAZ, CustomerEntryConstants.ENTRY_STATUS_DAZYS, CustomerEntryConstants.ENTRY_STATUS_AZYSTH, CustomerEntryConstants.ENTRY_STATUS_AZZS)) {
                                if (!StringUtil.equalsAny(entry.getApplyStatus(), "4","2")) {
                                    QueryDocumentRes queryDocumentRes = yueXiuContractService.queryDocumentStatus(entry.getId());
                                    if (queryDocumentRes.getProjectStatus().equals("APPROVING") || queryDocumentRes.getProjectStatus().equals("APPROVED") || queryDocumentRes.getProjectStatus().equals("CLOSED")) {
                                        try {
                                            yueXiuProjectOperatingService.returnIncomingApplication(entry, "设计变更");
                                        } catch (Exception e) {
                                            throw new BusinessException("退回进件失败,请确认电站进件状态");
                                        }
                                    }
                                }
                                try {
                                    yueXiuProjectOperatingService.againPushIncomingTy(entry, "oneIncoming",design.getId());
                                } catch (Exception e) {
                                    throw new BusinessException("提交进件失败," + e.getMessage());
                                }
                            }
                            if(StringUtil.isNotBlank(entry.getApplyStatus()) && (Double.valueOf(entry.getApplyStatus())>16 || "15".equals(entry.getApplyStatus()))){
                                //退回完工
                                operatingLeaseService.cancelProjectApply(application.getPartnersContractNumber(),"设计变更", SourceConstants.RETURN_TYPE_RETURN_TO_COMPLETION);
                                entryMsgService.saveCustomerEntryMsg(user,entry.getId(), CustomerEntryConstants.INCOMING_CANCEL,"设计变更 退回完工");
                                Operator operator=Operator.of(user);
                                Result result = entryService.accessProjectApplySec(entry,operator);
                                if (!"200".equals(result.getCode())) {
                                    throw new IllegalArgumentException("提交进件失败；"+result.getErrMsg());
                                }
                                entryService.saveByUpdate(entry);
                            }
                        }
                        break;
                    case PartnerConstants.PARTNER_ID_GF:
                        if ("0".equals(entry.getIsHistory())) {
                            if ((Double.parseDouble(entry.getApplyStatus()) > 5 && !StringUtil.equalsAny(entry.getApplyStatus(),
                                    CustomerEntryConstants.APPLY_STATUS_WGSH, CustomerEntryConstants.APPLY_STATUS_BWSHZ, CustomerEntryConstants.APPLY_STATUS_BWSHTG))
                                    || "6".equals(entry.getApplyStatus())) {
                                try {
                                    if (!CustomerEntryConstants.DESIGN_AUDIT_FLAG_JJSHBH.equals(entry.getApplyStatus())) {
                                        guangFaManagemnetService.designInfoUpdate(entry, design, application.getInputPieceId());
                                    }
                                } catch (Exception e) {
                                    throw new BusinessException("提交设计变更失败," + e.getMessage());
                                }
                            }
                        }
                        break;
                    case PartnerConstants.PARTNER_ID_HR: //合同处理
                        if(updateCapacity!=designCapacity || !model.equals(preModel)){
                            //作废合同，重新发起合同
//                            huaRongContractService.changeCauseContractSignAgain(entry.getId(),application.getPartnersContractNumber(),Operator.of(user),"设计信息变更引起合同重签",postZjRecord);
                            entryService.saveByUpdate(entry);
                        }
                }
            }
        }

        ItemManage itemManage = itemManageDao.getItemManagementByProcessInstanceId(design.getId(), FormUtils.ENTRY_CHANGE_SJBG);
        if (itemManage != null) {
            Operator operator = Operator.of(user);
            Date date = new Date();
            String result = pass ? ItemConstants.RESULT_OK : ItemConstants.RESULT_BACK;
            itemTaskDetailDao.addItemTaskDetail2(FormUtils.ENTRY_CHANGE_SJBG, itemManage.getApplicationId(), itemManage.getProcessInstanceId(), itemManage.getProcessInstanceId(), result, date, operator, "设计信息变更");
            itemManage.setStatus(ItemConstants.ITEM_STATUS_FINISH);
            itemManage.setEndTime(date);
            itemManageDao.save(itemManage);
            reviewDispatchDao.markDispatchFinish(itemManage);
        }
        return Result.ok();
    }

    @Transactional(rollbackFor = Exception.class)
    public Result auditDesignChangeHR(DesignChangeAuditReq req) {
        String changeId = req.getChangeId();
        CrmCustomerEntryChangeDesign design = customerEntryChangeDesignDao.get(changeId);
        CustomerEntry entry = entryDao.get(design.getEntryId());
        boolean pass = Objects.equals(req.getValue(), AUDIT_STATUS_PASS);
        GuardUtils.in(new String[]{AUDIT_STATUS_PASS, AUDIT_STATUS_REJECT}, req.getValue(), "审核状态不合法！");
        User user = UserUtils.getUser();
        DesignChangeAuditVo vo = new DesignChangeAuditVo();
        vo.setMsg(req.getMsg());
        vo.setChangeId(changeId);
        vo.setValue(req.getValue());
        vo.setUserId(user.getId());
        vo.setUserName(CrmUtils.getUserXM(user.getId()));
        int affected = customerEntryChangeDesignComponentDao.audit(vo);
        if (affected < 1) {
            return Result.fail("申请记录已经审核完成，请刷新页面！");
        }

        List<Record> components = customerEntryChangeDesignComponentDao.findByDesignId(design.getId());
        List<Record> postComponents = components.stream().filter(e -> Objects.equals(e.getStr("flag"), "1")).collect(Collectors.toList());
        //变化后的设计容量
        int updateCapacity = 0;
        String model = "";
        List<Record> postZjRecord=new ArrayList<>(); //组件变更的信息
        for (Record postComponent : postComponents) {
            if (Objects.equals(postComponent.getStr("item_type"), "3")) {
                postZjRecord.add(postComponent);
                updateCapacity += postComponent.getInt("num") * Integer.parseInt(postComponent.getStr("model"));
                if (StringUtil.isBlank(model)){
                    model = postComponent.getStr("model");
                }else {
                    model += model +","+ postComponent.getStr("model");
                }
            }
        }
        if (Objects.equals(req.getValue(), "1")) {
            List<Record> changeDetails = changeDesignDetailDao.getDesignDetailsByNumber(design.getNumber());
            String schemeTypeId = "";
            String schemeTypeName = "";
            String schemeId = "";
            String schemeName = "";
            for (Record changeDetail : changeDetails) {
                if (StringUtil.isBlank(schemeTypeId)){
                    schemeTypeId = changeDetail.getStr("scheme_type_id");
                }else {
                    schemeTypeId = schemeTypeId +","+ changeDetail.getStr("scheme_type_id");
                }
                if (StringUtil.isBlank(schemeTypeName)){
                    schemeTypeName = changeDetail.getStr("scheme_type_name");
                }else {
                    schemeTypeName = schemeTypeName +","+ changeDetail.getStr("scheme_type_name");
                }
                if (StringUtil.isBlank(schemeId)){
                    schemeId = changeDetail.getStr("scheme_id");
                } else {
                    schemeId = schemeId +","+ changeDetail.getStr("scheme_id");
                }
                if (StringUtil.isBlank(schemeName)){
                    schemeName = changeDetail.getStr("scheme_name");
                }else {
                    schemeName = schemeName +","+ changeDetail.getStr("scheme_name");
                }
                entryService.designChangeHR(changeDetail, postComponents);
            }
            entryService.designChangeHR2(entry,model,postComponents);
            SqlBuilder sb = new SqlBuilder()
                    .line("update crm_customer_entry")
                    .line("set scheme_type=:scheme_type," +
                            "scheme_type_id=:scheme_type_id," +
                            "scheme_type_name=:scheme_type_name," +
                            "scheme_id=:scheme_id," +
                            "scheme_name=:scheme_name," +
                            "design_change='1'," +
                            "component_spec=:component_spec," +
                            "design_change_time=:design_change_time," +
                            "design_capacity=:design_capacity "
                    )
                    .line("where id=:id ");
            SQLQuery query = entryDao.getSession().createSQLQuery(sb.build());
            query.setString("scheme_type", design.getSchemeType());
            query.setString("scheme_type_id", schemeTypeId);
            query.setString("scheme_type_name", schemeTypeName);
            query.setString("scheme_id", schemeId);
            query.setString("scheme_name", schemeName);
            query.setParameter("design_capacity", updateCapacity);
            query.setParameter("design_change_time", new Date());
            query.setString("component_spec", model);

            query.setString("id", entry.getId());
            int i = query.executeUpdate();
            if (i < 1) {
                throw new BusinessException("电站状态发生改变，请刷新后重试！");
            }
            // 电站信息同步
            entry.setSchemeType(design.getSchemeType());
            entry.setSchemeTypeId(schemeTypeId);
            entry.setSchemeTypeName(schemeTypeName);
            entry.setSchemeId(schemeId);
            entry.setSchemeName(schemeName);
            entry.setComponentSpec(model);
            entry.setDesignCapacity(updateCapacity);
            entryDao.save(entry);
        }
        String msg = (StringUtil.isNotBlank(req.getMsg()) ? ","+ req.getMsg() : "");
        String content = String.format("第%d次电站设计变更申请，审核" + (pass ? "通过" : "驳回") + msg, design.getNum());
        entryMsgService.saveCustomerEntryMsg(Operator.of(user), entry.getId(),
                (pass ? CustomerEntryConstants.ENTRY_CHANGE_PASS : CustomerEntryConstants.ENTRY_CHANGE_REFUSE), content, null);

        ItemManage itemManage = itemManageDao.getItemManagementByProcessInstanceId(design.getId(), FormUtils.ENTRY_CHANGE_SJBG);
        if (itemManage != null) {
            Operator operator = Operator.of(user);
            Date date = new Date();
            String result = pass ? ItemConstants.RESULT_OK : ItemConstants.RESULT_BACK;
            itemTaskDetailDao.addItemTaskDetail2(FormUtils.ENTRY_CHANGE_SJBG, itemManage.getApplicationId(), itemManage.getProcessInstanceId(), itemManage.getProcessInstanceId(), result, date, operator, "设计信息变更");
            itemManage.setStatus(ItemConstants.ITEM_STATUS_FINISH);
            itemManage.setEndTime(date);
            itemManageDao.save(itemManage);
            reviewDispatchDao.markDispatchFinish(itemManage);
        }
        return Result.ok();
    }
    /**
     * 校验 变更之后组件是否有变动
     * @return  true 无变动， false 有变动
     */
    public boolean checkZjEqual(String oId, String oSpec,
                                String nId, String nSpec, String partnerId) {
        if (StringUtil.isNotBlank(nId) && nId.equals(oId)) {
            return true;
        }
        if (PartnerConstants.PARTNER_ID_YX.equals(partnerId)) {
            // 越秀只要规格相同即可
            if (StringUtil.isBlank(nSpec)) {
                return false;
            }
            if (nSpec.equals(oSpec)) {
                return true;
            }
            return false;
        }
        else if (PartnerConstants.PARTNER_ID_GF.equals(partnerId)) {
            // 广发只要求规格相同即可
            if (StringUtil.isBlank(nSpec)) {
                return false;
            }
            if (nSpec.equals(oSpec)) {
                return true;
            }
            return false;
        }
        else if (PartnerConstants.PARTNER_ID_HR.equals(partnerId)) {
            // 华融要求规格相同即可
            if (StringUtil.isBlank(nSpec)) {
                return false;
            }
            if (nSpec.equals(oSpec)) {
                return true;
            }
            return false;
        }
        return false;
    }
    private CrmCustomerEntryChangeDesignComponent componentFromReq(AddDesignChangeComponentReq req, String changeId, User user,String projectId) {
        CrmCustomerEntryChangeDesignComponent ret = new CrmCustomerEntryChangeDesignComponent();
        ret.setDesignChangeId(changeId);
        ret.setItemType(req.getType());
        ret.setItemId(req.getItemId());
        ret.setNum(req.getNum());
        ret.setFlag(req.getFlag());
        ret.setModel(req.getSpec());
        GuardUtils.in(new String[]{"0", "1"}, req.getFlag(), "flag must be 0 or 1");
        ret.setStatus("0"); // 0 正常
        ret.setCreateTime(new Date());
        ret.setCreateBy(user.getId());
        ret.setProjectId(projectId);
        return ret;
    }

    @Transactional(rollbackFor = Exception.class)
    public Result cancelAddDesign(String changeId) {
        CrmCustomerEntryChangeDesign design = customerEntryChangeDesignDao.get(changeId);
        if (!Objects.equals(design.getStatus(), CustomerEntryChangeDesignConstant.AUDIT_STATUS_WAIT)) {
            return Result.fail("审核状态已经发生变更，请刷新页面！");
        }
        int affected = customerEntryChangeDesignDao.cancel(changeId);
        if (affected < 1) {
            return Result.fail("审核状态已经发生变更，请刷新页面！");
        }
        User user = UserUtils.getUser();
        ItemManage itemManage = itemManageDao.getItemManagementByProcessInstanceId(design.getId(), FormUtils.ENTRY_CHANGE_SJBG);
        if (itemManage != null) {
            itemManage.setStatus(ItemConstants.ITEM_STATUS_CANCEL);
            itemManage.setEndTime(new Date());
            itemManageDao.save(itemManage);
        }
        String content = String.format("第%d次电站设计变更申请，撤回", design.getNum());
        entryMsgService.saveCustomerEntryMsg(Operator.of(user), design.getEntryId(), CustomerEntryConstants.ENTRY_CHANGE_CANCEL
                , content, null);
        return Result.ok();
    }
}
