package com.yeejoin.amos.boot.module.jg.biz.edit.process.equip;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.entity.TzsBaseEntity;
import com.yeejoin.amos.boot.module.common.biz.event.CommonPublisher;
import com.yeejoin.amos.boot.module.common.biz.refresh.DataRefreshEvent;
import com.yeejoin.amos.boot.module.jg.api.common.BizCommonConstant;
import com.yeejoin.amos.boot.module.jg.api.dto.FieldChangeMeta;
import com.yeejoin.amos.boot.module.jg.api.enums.CylinderTypeEnum;
import com.yeejoin.amos.boot.module.jg.biz.edit.esUpdate.service.EsUpdateService;
import com.yeejoin.amos.boot.module.jg.biz.edit.process.biz.DefaultBizDataChangeHandler;
import com.yeejoin.amos.boot.module.jg.biz.edit.process.biz.strategy.IBizDataChangeHandleStrategy;
import com.yeejoin.amos.boot.module.jg.biz.edit.process.equip.strategy.HandleResult;
import com.yeejoin.amos.boot.module.jg.biz.edit.process.equip.strategy.IEquipChangeDataProcessStrategy;
import com.yeejoin.amos.boot.module.ymt.api.entity.*;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

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

/**
 * 单个维护设备-策略实现类
 */
@Component
@RequiredArgsConstructor
public class SingleEquipChangeProcess implements IEquipChangeDataProcessStrategy {


    private final CommonEquipDataProcessService commonEquipDataProcessService;

    private final EsUpdateService esUpdateService;

    private final CommonPublisher publisher;


    @Override
    public HandleResult handle(Map<String, Object> changeData, String record) {
        JSONObject changeJson = new JSONObject(changeData);
        List<FieldChangeMeta> allChangeColumns = new ArrayList<>();

        IdxBizJgUseInfo useInfoOld = commonEquipDataProcessService.getJgUseRegistrationService().getUseInfoMapper().selectOne(new LambdaQueryWrapper<IdxBizJgUseInfo>().eq(IdxBizJgUseInfo::getRecord, record));
        IdxBizJgUseInfo useInfoNew = BeanUtil.copyProperties(useInfoOld, IdxBizJgUseInfo.class);
        CommonEquipDataProcessService.castMap2Bean(changeJson, useInfoNew);
        useInfoNew.setSequenceNbr(useInfoOld.getSequenceNbr());
        commonEquipDataProcessService.setNameByCode2UseInfo(useInfoNew);

        IdxBizJgRegisterInfo registerInfoOld = commonEquipDataProcessService.getJgUseRegistrationService().getIdxBizJgRegisterInfoService().getOne(new LambdaQueryWrapper<IdxBizJgRegisterInfo>().eq(IdxBizJgRegisterInfo::getRecord, record));
        IdxBizJgRegisterInfo registerInfoNew = BeanUtil.copyProperties(registerInfoOld, IdxBizJgRegisterInfo.class);
        CommonEquipDataProcessService.castMap2Bean(changeJson, registerInfoNew);
        registerInfoNew.setSequenceNbr(registerInfoOld.getSequenceNbr());

        // 历史有证设备检验（台套类设备+气瓶）
        beforeCheckForUseOrgCode(useInfoOld, registerInfoNew);

        IdxBizJgFactoryInfo factoryInfoOld = commonEquipDataProcessService.getJgFactoryInfoMapper().selectOne(new LambdaQueryWrapper<IdxBizJgFactoryInfo>().eq(IdxBizJgFactoryInfo::getRecord, record));
        IdxBizJgFactoryInfo factoryInfoNew = BeanUtil.copyProperties(factoryInfoOld, IdxBizJgFactoryInfo.class);
        CommonEquipDataProcessService.castMap2Bean(changeJson, factoryInfoNew);
        factoryInfoNew.setSequenceNbr(factoryInfoOld.getSequenceNbr());

        IdxBizJgDesignInfo designInfoOld = commonEquipDataProcessService.getIdxBizJgDesignInfoMapper().selectOne(new LambdaQueryWrapper<IdxBizJgDesignInfo>().eq(IdxBizJgDesignInfo::getRecord, record));
        IdxBizJgDesignInfo designInfoNew = BeanUtil.copyProperties(designInfoOld, IdxBizJgDesignInfo.class);
        CommonEquipDataProcessService.castMap2Bean(changeJson, designInfoNew);
        designInfoNew.setSequenceNbr(designInfoOld.getSequenceNbr());

        IdxBizJgOtherInfo otherInfoOld = commonEquipDataProcessService.getIdxBizJgOtherInfoMapper().selectOne(new LambdaQueryWrapper<IdxBizJgOtherInfo>().eq(IdxBizJgOtherInfo::getRecord, record));
        IdxBizJgOtherInfo otherInfoNew = BeanUtil.copyProperties(otherInfoOld, IdxBizJgOtherInfo.class);
        CommonEquipDataProcessService.castMap2Bean(changeJson, otherInfoNew);
        otherInfoNew.setSequenceNbr(otherInfoOld.getSequenceNbr());

        IdxBizJgSupervisionInfo idxBizJgSupervisionInfoOld = commonEquipDataProcessService.getJgUseRegistrationService().getIdxBizJgSupervisionInfoMapper().selectOne(new LambdaQueryWrapper<IdxBizJgSupervisionInfo>().eq(IdxBizJgSupervisionInfo::getRecord, record));
        IdxBizJgSupervisionInfo idxBizJgSupervisionInfoNew = BeanUtil.copyProperties(idxBizJgSupervisionInfoOld, IdxBizJgSupervisionInfo.class);
        CommonEquipDataProcessService.castMap2Bean(changeJson, idxBizJgSupervisionInfoNew);
        idxBizJgSupervisionInfoNew.setSequenceNbr(idxBizJgSupervisionInfoOld.getSequenceNbr());
        this.setNameByCode2SupervisionInfo(idxBizJgSupervisionInfoNew);

        String jySeq = changeJson.getString("jySeq");
        String maintenanceSeq = changeJson.getString("maintenanceSeq");
        String constructionInfoSeq = changeJson.getString("constructionInfoSeq");
        if (jySeq != null) {
            IdxBizJgInspectionDetectionInfo inspectionDetectionInfoOld = commonEquipDataProcessService.getJgUseRegistrationService().getInspectionDetectionInfoService().getById(jySeq);
            IdxBizJgInspectionDetectionInfo inspectionDetectionInfoNew = BeanUtil.copyProperties(inspectionDetectionInfoOld, IdxBizJgInspectionDetectionInfo.class);
            CommonEquipDataProcessService.castMap2Bean(changeJson, inspectionDetectionInfoNew);
            inspectionDetectionInfoNew.setSequenceNbr(inspectionDetectionInfoOld.getSequenceNbr());
            List<FieldChangeMeta> inspectionFieldChangeMetas = commonEquipDataProcessService.simpleTrackAndUpdate(commonEquipDataProcessService.getJgUseRegistrationService().getInspectionDetectionInfoService().getBaseMapper(), inspectionDetectionInfoOld, inspectionDetectionInfoNew, useInfoNew.getRecord(), "SEQUENCE_NBR", inspectionDetectionInfoOld.getSequenceNbr());
            allChangeColumns.addAll(inspectionFieldChangeMetas);
            esUpdateService.updateEsData(record, inspectionDetectionInfoNew);
        }
        if (maintenanceSeq != null) {
            IdxBizJgMaintenanceRecordInfo idxBizJgMaintenanceRecordInfoOld = commonEquipDataProcessService.getJgUseRegistrationService().getIdxBizJgMaintenanceRecordInfoService().getById(maintenanceSeq);
            IdxBizJgMaintenanceRecordInfo idxBizJgMaintenanceRecordInfoNew = BeanUtil.copyProperties(idxBizJgMaintenanceRecordInfoOld, IdxBizJgMaintenanceRecordInfo.class);
            CommonEquipDataProcessService.castMap2Bean(changeJson, idxBizJgMaintenanceRecordInfoNew);
            idxBizJgMaintenanceRecordInfoNew.setSequenceNbr(idxBizJgMaintenanceRecordInfoOld.getSequenceNbr());
            List<FieldChangeMeta> idxBizJgMaintenanceFieldChangeMetas = commonEquipDataProcessService.simpleTrackAndUpdate(commonEquipDataProcessService.getJgUseRegistrationService().getIdxBizJgMaintenanceRecordInfoService().getBaseMapper(), idxBizJgMaintenanceRecordInfoOld, idxBizJgMaintenanceRecordInfoNew, useInfoNew.getRecord(), "SEQUENCE_NBR", idxBizJgMaintenanceRecordInfoOld.getSequenceNbr());
            allChangeColumns.addAll(idxBizJgMaintenanceFieldChangeMetas);
        }
        if (constructionInfoSeq != null) {
            IdxBizJgConstructionInfo constructionInfoOld = commonEquipDataProcessService.getJgUseRegistrationService().getIdxBizJgConstructionInfoService().getById(constructionInfoSeq);
            IdxBizJgConstructionInfo constructionInfoNew = BeanUtil.copyProperties(constructionInfoOld, IdxBizJgConstructionInfo.class);
            CommonEquipDataProcessService.castMap2Bean(changeJson, constructionInfoNew);
            constructionInfoNew.setSequenceNbr(constructionInfoOld.getSequenceNbr());
            commonEquipDataProcessService.setNameByCode2ConstructionInfo(constructionInfoNew);
            List<FieldChangeMeta> constructionInfoFieldChangeMetas = commonEquipDataProcessService.simpleTrackAndUpdate(commonEquipDataProcessService.getJgUseRegistrationService().getIdxBizJgConstructionInfoService().getBaseMapper(), constructionInfoOld, constructionInfoNew, useInfoNew.getRecord(), "SEQUENCE_NBR", constructionInfoOld.getSequenceNbr());
            allChangeColumns.addAll(constructionInfoFieldChangeMetas);
        }
        // 前置校验、新数据解析
        commonEquipDataProcessService.checkValidField2(record, registerInfoNew, null, null, null);
        commonEquipDataProcessService.checkValidField2(record, factoryInfoNew, registerInfoNew.getEquList(), registerInfoNew.getEquCategory(), registerInfoNew.getEquDefine());
        commonEquipDataProcessService.checkValidField2(record, designInfoNew, registerInfoNew.getEquList(), registerInfoNew.getEquCategory(), registerInfoNew.getEquDefine());

        // 设备制造、设计、注册信息业务处理落库
        List<FieldChangeMeta> useInfoFieldChangeMetas = commonEquipDataProcessService.simpleTrackAndUpdate(commonEquipDataProcessService.getJgUseRegistrationService().getUseInfoMapper(), useInfoOld, useInfoNew, useInfoNew.getRecord(), "record", useInfoNew.getRecord());
        allChangeColumns.addAll(useInfoFieldChangeMetas);

        List<FieldChangeMeta> registerInfoFieldChangeMetas = commonEquipDataProcessService.simpleTrackAndUpdate(commonEquipDataProcessService.getJgUseRegistrationService().getIdxBizJgRegisterInfoService().getBaseMapper(), registerInfoOld, registerInfoNew, useInfoNew.getRecord(), "record", useInfoNew.getRecord());
        allChangeColumns.addAll(registerInfoFieldChangeMetas);

        List<FieldChangeMeta> factoryInfoFieldChangeMetas = commonEquipDataProcessService.simpleTrackAndUpdate(commonEquipDataProcessService.getJgFactoryInfoMapper(), factoryInfoOld, factoryInfoNew, useInfoNew.getRecord(), "record", useInfoNew.getRecord());
        allChangeColumns.addAll(factoryInfoFieldChangeMetas);

        List<FieldChangeMeta> designInfoFieldChangeMetas = commonEquipDataProcessService.simpleTrackAndUpdate(commonEquipDataProcessService.getIdxBizJgDesignInfoMapper(), designInfoOld, designInfoNew, useInfoNew.getRecord(), "record", useInfoNew.getRecord());
        allChangeColumns.addAll(designInfoFieldChangeMetas);

        List<FieldChangeMeta> otherInfoFieldChangeMetas = commonEquipDataProcessService.simpleTrackAndUpdate(commonEquipDataProcessService.getIdxBizJgOtherInfoMapper(), otherInfoOld, otherInfoNew, useInfoNew.getRecord(), "record", useInfoNew.getRecord());
        allChangeColumns.addAll(otherInfoFieldChangeMetas);

        List<FieldChangeMeta> idxBizJgSupervisionInfoFieldChangeMetas = commonEquipDataProcessService.simpleTrackAndUpdate(commonEquipDataProcessService.getJgUseRegistrationService().getIdxBizJgSupervisionInfoMapper(), idxBizJgSupervisionInfoOld, idxBizJgSupervisionInfoNew, useInfoNew.getRecord(), "record", useInfoNew.getRecord());
        allChangeColumns.addAll(idxBizJgSupervisionInfoFieldChangeMetas);

        esUpdateService.updateEsData(record, registerInfoNew);
        esUpdateService.updateEsData(record, useInfoNew);
        esUpdateService.updateEsData(record, designInfoNew);
        esUpdateService.updateEsData(record, otherInfoNew);
        esUpdateService.updateEsData(record, factoryInfoNew);
        esUpdateService.updateEsData(record, idxBizJgSupervisionInfoNew);

        // 如果是气瓶则按照证更新其他同证下的气瓶字段
        this.updateOtherEquipInSameCert(useInfoNew, registerInfoNew, registerInfoOld, allChangeColumns);
        // 设备技术参数入库处理
        commonEquipDataProcessService.updateTechParamInfo(registerInfoOld.getEquList(), record, changeData, allChangeColumns);
        // 发送数据刷新消息
        publisher.publish(new DataRefreshEvent(this, Collections.singletonList(record), DataRefreshEvent.DataType.equipment.name(), DataRefreshEvent.Operation.UPDATE));
        return HandleResult.builder().fieldChangeMetas(allChangeColumns).build();
    }

    private void updateOtherEquipInSameCert(IdxBizJgUseInfo useInfoNew, IdxBizJgRegisterInfo registerInfoNew, IdxBizJgRegisterInfo registerInfoOld, List<FieldChangeMeta> allChangeColumns) {
        // 气瓶下的相同的使用登记证编号设备更新
        String useOrgCode = registerInfoOld.getUseOrgCode();
        if (BizCommonConstant.EQU_CATEGORY_CYLINDER.equals(registerInfoNew.getEquCategory()) && StringUtils.isNotEmpty(useOrgCode)) {
            // 查询相同的使用登记证编号的设备不包含源设备
            List<IdxBizJgRegisterInfo> equipInOneCerts = commonEquipDataProcessService.getJgUseRegistrationService()
                    .getIdxBizJgRegisterInfoService()
                    .list(new LambdaQueryWrapper<IdxBizJgRegisterInfo>()
                            .eq(IdxBizJgRegisterInfo::getUseOrgCode, useOrgCode)
                            .ne(IdxBizJgRegisterInfo::getRecord, registerInfoOld.getRecord())
                            .select(TzsBaseEntity::getSequenceNbr, IdxBizJgRegisterInfo::getRecord));
            equipInOneCerts.forEach(equip -> {
                String record = equip.getRecord();
                // 使用信息
                IdxBizJgUseInfo useInfoOtherOld = commonEquipDataProcessService.getJgUseRegistrationService().getUseInfoMapper().selectOne(new LambdaQueryWrapper<IdxBizJgUseInfo>().eq(IdxBizJgUseInfo::getRecord, record));
                IdxBizJgUseInfo useInfoOtherNew = BeanUtil.copyProperties(useInfoOtherOld, IdxBizJgUseInfo.class);
                useInfoOtherNew.setProvince(useInfoNew.getProvince());
                useInfoOtherNew.setProvinceName(useInfoNew.getProvinceName());
                useInfoOtherNew.setCity(useInfoNew.getCity());
                useInfoOtherNew.setCityName(useInfoNew.getCityName());
                useInfoOtherNew.setCounty(useInfoNew.getCounty());
                useInfoOtherNew.setCountyName(useInfoNew.getCountyName());
                useInfoOtherNew.setFactoryUseSiteStreet(useInfoNew.getFactoryUseSiteStreet());
                useInfoOtherNew.setStreetName(useInfoNew.getStreetName());
                useInfoOtherNew.setAddress(useInfoNew.getAddress());
                useInfoOtherNew.setSafetyManager(useInfoNew.getSafetyManager());
                useInfoOtherNew.setPhone(useInfoNew.getPhone());
                useInfoOtherNew.setIsNotXiXian(useInfoNew.getIsNotXiXian());
                useInfoOtherNew.setEstateUnitCreditCode(useInfoNew.getEstateUnitCreditCode());
                useInfoOtherNew.setEstateUnitName(useInfoNew.getEstateUnitName());
                useInfoOtherNew.setUseDate(useInfoNew.getUseDate());
                useInfoOtherNew.setUsePlace(useInfoNew.getUsePlace());
                useInfoOtherNew.setLongitudeLatitude(useInfoNew.getLongitudeLatitude());

                // 注册信息
                IdxBizJgRegisterInfo registerInfoOtherOld = commonEquipDataProcessService.getJgUseRegistrationService().getIdxBizJgRegisterInfoService().getOne(new LambdaQueryWrapper<IdxBizJgRegisterInfo>().eq(IdxBizJgRegisterInfo::getRecord, record));
                IdxBizJgRegisterInfo registerInfoOtherNew = BeanUtil.copyProperties(registerInfoOtherOld, IdxBizJgRegisterInfo.class);
                registerInfoOtherNew.setUseOrgCode(registerInfoNew.getUseOrgCode());
                registerInfoOtherNew.setCarNumber(registerInfoNew.getCarNumber());

                List<FieldChangeMeta> useInfoFieldChangeMetas = commonEquipDataProcessService.simpleTrackAndUpdate(commonEquipDataProcessService.getJgUseRegistrationService().getUseInfoMapper(), useInfoOtherOld, useInfoOtherNew, record, "record", record);
                allChangeColumns.addAll(useInfoFieldChangeMetas);

                List<FieldChangeMeta> registerInfoFieldChangeMetas = commonEquipDataProcessService.simpleTrackAndUpdate(commonEquipDataProcessService.getJgUseRegistrationService().getIdxBizJgRegisterInfoService().getBaseMapper(), registerInfoOtherOld, registerInfoOtherNew, record, "record", record);
                allChangeColumns.addAll(registerInfoFieldChangeMetas);
            });
        }
    }

    private void setNameByCode2SupervisionInfo(IdxBizJgSupervisionInfo idxBizJgSupervisionInfo) {
        // 按照org_code查询
        if (StringUtils.isNotEmpty(idxBizJgSupervisionInfo.getOrgBranchCode())) {
            CompanyBo companyBo = commonEquipDataProcessService.getCommonMapper().queryCompanyByOrgCode(idxBizJgSupervisionInfo.getOrgBranchCode());
            idxBizJgSupervisionInfo.setOrgBranchCode(companyBo.getOrgCode());
            idxBizJgSupervisionInfo.setOrgBranchName(companyBo.getCompanyName());
            idxBizJgSupervisionInfo.setCompanyOrgBranchCode(companyBo.getCompanyCode());
        }
    }


    private void beforeCheckForUseOrgCode(IdxBizJgUseInfo useInfoOld, IdxBizJgRegisterInfo registerInfoNew) {
        // 1.使用登记证编辑时重复性校验
        if (!CylinderTypeEnum.CYLINDER.getCode().equals(registerInfoNew.getEquCategory())) {  // 非气瓶逻辑,所有设备不能重复
            if (useInfoOld.getDataSource().equals("jg_his") && StringUtils.isNotEmpty(registerInfoNew.getUseOrgCode())) {
                Boolean isUsed = commonEquipDataProcessService.getCommonService().useRegistrationCertificateAccountUnique(registerInfoNew.getUseOrgCode(), useInfoOld.getRecord());
                if (isUsed) {
                    throw new BadRequest("使用登记证编号已存在！");
                }
            }
        } else {                                                                            // 气瓶逻辑，使用单位下不能重复
            if (StringUtils.isNotEmpty(useInfoOld.getUseUnitCreditCode()) && StringUtils.isNotEmpty(registerInfoNew.getUseOrgCode())) {
                // 需求 35094 历史设备（有使用登记证）需按证录入。录入时先录入使用登记证编号。
                // 需验证录入的使用登记证编号平台是否跟当前用户（使用单位类型）一致，如跟当前用户不一致，系统给出提示“该使用登记证编号”已被“单位名称“使用”，请确认后再录入”。
                // 历史设备不限制使用登记证编号在一个单位重复录入，但需验证使用登记证编号+单位内编号唯一。（下面方法checkFactoryNumUniqueWithGasCylinder中已经校验）
                List<String> occupiedUseUnitNames = commonEquipDataProcessService.getCommonService().isRegistrationNumberUsedByOtherUnits(registerInfoNew.getUseOrgCode(), useInfoOld.getUseUnitCreditCode());
                if (!occupiedUseUnitNames.isEmpty()) {
                    throw new BadRequest("该使用登记证编号已被【" + String.join(",", occupiedUseUnitNames) + "】使用，请确认后再录入！");
                }
            }
        }

    }

    @Override
    public IBizDataChangeHandleStrategy.ModelType canHandleMode() {
        return DefaultBizDataChangeHandler.ModelType.singleEquip;
    }

}
