package com.yeejoin.amos.boot.module.jg.biz.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.biz.common.utils.SnowflakeIdUtil;
import com.yeejoin.amos.boot.module.common.api.dao.ESEquipmentCategory;
import com.yeejoin.amos.boot.module.common.api.dao.EsEquipmentDao;
import com.yeejoin.amos.boot.module.common.api.dto.ESEquipmentCategoryDto;
import com.yeejoin.amos.boot.module.common.api.entity.ESEquipmentInfo;
import com.yeejoin.amos.boot.module.jg.api.dto.ShCarDto;
import com.yeejoin.amos.boot.module.jg.api.entity.*;
import com.yeejoin.amos.boot.module.jg.api.enums.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.CertificateStatusEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.CompanyTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.mapper.ShCarMapper;
import com.yeejoin.amos.boot.module.jg.api.service.IShCarService;
import com.yeejoin.amos.boot.module.jg.biz.event.publisher.EventPublisher;
import com.yeejoin.amos.boot.module.jg.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.reminder.core.event.EquipCreateOrEditEvent;
import com.yeejoin.amos.boot.module.ymt.api.entity.*;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.DictionarieValueModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.alibaba.fastjson.JSON.toJSONString;
import static com.yeejoin.amos.boot.module.jg.api.enums.VehicleApanageEnum.XIAN_YANG;
import static com.yeejoin.amos.boot.module.jg.api.enums.VehicleApanageEnum.XI_XIAN;

/**
 * 三环系统-车辆信息表服务实现类
 *
 * @author system_generator
 * @date 2024-11-08
 */
@Slf4j
@Service
public class ShCarServiceImpl extends BaseService<ShCar, ShCar, ShCarMapper> implements IShCarService {

    @Resource
    private RedisUtils redisUtils;
    @Resource
    ShCarEquServiceImpl shCarEquServiceImpl;
    @Resource
    private SnowflakeIdUtil sequence;
    @Resource
    private IdxBizJgUseInfoServiceImpl idxBizJgUseInfoService;
    @Resource
    private IdxBizJgConstructionInfoServiceImpl idxBizJgConstructionInfoService;
    @Resource
    private IdxBizJgDesignInfoServiceImpl idxBizJgDesignInfoService;
    @Resource
    private IdxBizJgFactoryInfoServiceImpl idxBizJgFactoryInfoService;
    @Resource
    private IdxBizJgInspectionDetectionInfoServiceImpl idxBizJgInspectionDetectionInfoService;
    @Resource
    private IdxBizJgMaintenanceRecordInfoServiceImpl idxBizJgMaintenanceRecordInfoService;
    @Resource
    private IdxBizJgOtherInfoServiceImpl idxBizJgOtherInfoService;
    @Resource
    private IdxBizJgRegisterInfoServiceImpl idxBizJgRegisterInfoService;
    @Resource
    private IdxBizJgSupervisionInfoServiceImpl idxBizJgSupervisionInfoService;
    @Resource
    private IdxBizJgTechParamsVesselServiceImpl idxBizJgTechParamsVesselService;
    @Resource
    private ESEquipmentCategory esEquipmentCategory;
    @Resource
    private EsEquipmentDao esEquipmentDao;
    @Resource
    private TzsServiceFeignClient tzsServiceFeignClient;
    @Resource
    private JgVehicleInformationServiceImpl vehicleInformationService;
    @Resource
    private JgVehicleInformationEqServiceImpl vehicleInformationEqService;
    @Resource
    private JgUseRegistrationManageServiceImpl useRegistrationManageService;
    @Resource
    private JgChangeVehicleRegistrationUnitServiceImpl changeVehicleRegistrationUnitService;
    @Resource
    private JgCertificateChangeRecordServiceImpl certificateChangeRecordService;
    @Resource
    private JgCertificateChangeRecordEqServiceImpl certificateChangeRecordEqService;
    @Resource
    private CommonServiceImpl commonService;

    private final ShCarMapper shCarMapper;

    @Autowired
    private EventPublisher eventPublisher;

    public ShCarServiceImpl(ShCarMapper shCarMapper) {
        this.shCarMapper = shCarMapper;
    }

    /**
     * 分页查询
     */
    public Page<ShCar> queryForShCarPage(Page<ShCar> page) {
        return this.queryForPage(page, null, false);
    }

    /**
     * 列表查询 示例
     */
    public List<ShCar> queryForShCarList() {
        return this.queryForList("", false);
    }

    @Override
    public Page<ShCarDto> queryForShCarPage(Page<ShCarDto> page, ShCarDto dto) {
        return shCarMapper.queryForshCarPage(page, dto);
    }

    @Override
    public ShCar searchForSanHan(Map<?, ?> map) {
        ShCar shCar = null;
        for (Object value : map.values()) {
            String sanHuanInputValue = String.valueOf(value);
            // 如果值为空，直接跳过
            if (ValidationUtil.isEmpty(sanHuanInputValue)) {
                continue;
            }
            // 查询 ShCar 表
            shCar = this.getBaseMapper()
                    .selectList(new LambdaQueryWrapper<ShCar>()
                            .eq(ShCar::getClaimedFlag, Boolean.FALSE)
                            .and(w -> w
                                    .eq(ShCar::getCarNumber, sanHuanInputValue)
                                    .or()
                                    .eq(ShCar::getUseRegistrationCode, sanHuanInputValue)
                                    .or()
                                    .eq(ShCar::getFrameNumber, sanHuanInputValue)
                            )
                    ).stream().findFirst().orElse(null);
            // 如果找到符合条件的 ShCar，再检查该使用登记证号、车牌号或者车架号是否已经在系统中通过历史设备登记入库
            if (shCar != null && !ValidationUtil.isEmpty(shCar.getSequenceNbr()) && !alreadyExist(sanHuanInputValue)) {
                return shCar;
            }
            // 查询 ShCarEqu 表
            Optional<ShCarEqu> carEqu = shCarEquServiceImpl.getBaseMapper()
                    .selectList(new LambdaQueryWrapper<ShCarEqu>()
                            .eq(ShCarEqu::getEquCode, sanHuanInputValue))
                    .stream().findFirst();
            // 如果 ShCarEqu 存在，继续查询 ShCar
            if (carEqu.isPresent()) {
                shCar = this.getBaseMapper()
                        .selectList(new LambdaQueryWrapper<ShCar>()
                                .eq(ShCar::getClaimedFlag, Boolean.FALSE)
                                .eq(ShCar::getSequenceNbr, carEqu.get().getCarId())
                        ).stream().findFirst().orElse(null);
                // 如果找到，再检查该使用登记证号、车牌号或者车架号是否已经在系统中通过历史设备登记入库
                if (shCar != null && !ValidationUtil.isEmpty(shCar.getSequenceNbr()) && !alreadyExist(sanHuanInputValue)) {
                    return shCar;
                }
            }
        }
        // 如果未找到，返回空对象
        return new ShCar();
    }

    /**
     * 判断是否已存在在一码通库中
     *
     * @param value 登记证号、车牌号或者车架号
     * @return result
     */
    public Boolean alreadyExist(String value) {
        return this.baseMapper.alreadyExist(value) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean claim(String claimOneself, Map<String, Object> paramMap) {
        List<String> records = new ArrayList<>();
        try {
            boolean isOneSelf = Boolean.parseBoolean(claimOneself);
            HashMap<Object, Object> completeDataSanHuanMap = JSON.parseObject(toJSONString(paramMap.get("completeDataSanHuan")), HashMap.class);
            // 自己认领
            if (isOneSelf) {
                records = this.claimOneselfMet(true, completeDataSanHuanMap);
            }
            // 帮别人认领 + 单位变更登记到自己名下
            if (!isOneSelf) {
                HashMap<String, Object> gasCylinderChangeMap = JSON.parseObject(toJSONString(paramMap.get("gasCylinderChange")), HashMap.class);
                records = this.claimOthersMet(completeDataSanHuanMap, gasCylinderChangeMap);
            }
        } catch (Exception exception) {
            this.handleClaimFailed(records);
            throw new BadRequest(exception.getMessage());
        }

        return Boolean.TRUE;
    }

    /**
     * 帮别人认领 + 单位变更登记到自己名下
     *
     * @param completeDataSanHuanMap 认领表单信息
     * @param gasCylinderChangeMap   车用气瓶单位变更登记表单信息
     * @return result
     */
    private List<String> claimOthersMet(HashMap<?, ?> completeDataSanHuanMap, HashMap<String, Object> gasCylinderChangeMap) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        // 认领设备及证管理信息完善
        List<String> records = this.claimOneselfMet(false, completeDataSanHuanMap);
        // 发起车用气瓶单位变更登记
        List<Map<String, Object>> equList = changeVehicleRegistrationUnitService.getBaseMapper().getEquList(records)
                .stream()
                .peek(x -> x.put("carNumber", completeDataSanHuanMap.get("carNumber")))
                .peek(x -> x.put("chargingMedium", changeVehicleRegistrationUnitService.getFillingMediumMap().get(x.get("chargingMedium"))))
                .collect(Collectors.toList());
        gasCylinderChangeMap.put("useUnitCreditCode", String.format("%s_%s", completeDataSanHuanMap.get("useUnitName"), completeDataSanHuanMap.get("useUnitCreditCode")));
        gasCylinderChangeMap.put("dataList", equList);
        gasCylinderChangeMap.put("submit", "1");
        gasCylinderChangeMap.put("formType", "add");
        gasCylinderChangeMap.put("businessCode", ApplicationFormTypeEnum.DWBG.getBusinessCode());
        gasCylinderChangeMap.put("receiveOrgCode", gasCylinderChangeMap.get("receiveOrgCode"));
        gasCylinderChangeMap.put("receiveCompanyCode", gasCylinderChangeMap.get("receiveOrgCode"));
        changeVehicleRegistrationUnitService.saveMessage(new JSONObject(gasCylinderChangeMap), reginParams);
        // 保存字典值 原三环使用单位
        List<DictionarieValueModel> oldUseUnit = Systemctl.dictionarieClient.dictValues("OLD_USE_UNIT").getResult();
        boolean hasKey = oldUseUnit.stream().anyMatch(x -> x.getDictDataKey().equals(completeDataSanHuanMap.get("useUnitName")));
        if (!hasKey) {
            DictionarieValueModel dictionarieValueModel = new DictionarieValueModel();
            dictionarieValueModel.setDictCode("OLD_USE_UNIT");
            dictionarieValueModel.setDictDataValue((String) completeDataSanHuanMap.get("useUnitName"));
            dictionarieValueModel.setDictDataKey((String) completeDataSanHuanMap.get("useUnitName"));
            Systemctl.dictionarieClient.createValue(dictionarieValueModel);
        }
        return records;
    }

    /**
     * 认领 设备 证 。。。
     *
     * @param isOneSelf 是否自己认领
     * @param paramMap  入参
     * @return 设备record集合
     */
    private List<String> claimOneselfMet(Boolean isOneSelf, Map<?, ?> paramMap) {
        List<String> records = new ArrayList<>();
        // ShCar表的seq
        String shCarSequenceNbr = String.valueOf(paramMap.get("sequenceNbr"));
        if (ValidationUtil.isEmpty(shCarSequenceNbr)) {
            throw new BadRequest("数据异常!");
        }

        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())) + "", ReginParams.class);
        JSONArray equList = JSON.parseArray(JSON.toJSONString(paramMap.get("equList")));

        // 0. 必要校验
        // 0.1 使用登记证的唯一校验
        String useRegistrationCode = String.valueOf(paramMap.get("useRegistrationCode"));
        Boolean used = commonService.useRegistrationCertificateAccountUnique(useRegistrationCode, null);
        if (used) {
            throw new BadRequest("使用登记证编号已存在！");
        }
        // 0.2 设备代码的唯一校验
        Set<String> equCodeSet = equList.stream().map(equ -> {
            JSONObject jsonObject = JSON.parseObject(toJSONString(equ));
            return jsonObject.getString("equCode");
        }).filter(equCode -> equCode != null && !equCode.trim().isEmpty()) // 过滤掉 null 和空字符串
                .collect(Collectors.toSet());
        if (equCodeSet.isEmpty()) {
            throw new BadRequest("设备代码不能为空！");
        }
        if (equCodeSet.size() < equList.size())
            throw new BadRequest("设备代码重复！");
        equCodeSet.forEach(equCode -> {
            Boolean useFlag = commonService.checkEquCodeUniqueness(equCode);
            if (useFlag) {
                throw new BadRequest("设备代码已存在系统中！");
            }
        });
        // 0.3 出厂编号/产品编号的唯一校验
        Set<String> factoryNumSet = equList.stream().map(equ -> {
            JSONObject jsonObject = JSON.parseObject(toJSONString(equ));
            return jsonObject.getString("factoryNum");
        }).filter(factoryNum -> factoryNum != null && !factoryNum.trim().isEmpty()) // 过滤掉 null 和空字符串
                .collect(Collectors.toSet());
        if (factoryNumSet.isEmpty()) {
            throw new BadRequest("出厂编号/产品编号不能为空！");
        }
        if (factoryNumSet.size() < equList.size())
            throw new BadRequest("出厂编号/产品编码重复！");
        factoryNumSet.forEach(factoryNum -> {
            Integer useFlag = commonService.checkFactoryNumUniquenessForVehicleCylinder(factoryNum, null);
            if (useFlag > 0) {
                throw new BadRequest("出厂编号/产品编码已存在系统中！");
            }
        });

        try {
            // 清除seq，避免后续所有 业务表 都使用此 seq
            paramMap.remove("sequenceNbr");

            // 1. 生成设备信息 + 保存es
            records = this.claimGenEquInfo(useRegistrationCode, paramMap, equList, reginParams, isOneSelf);

            // 2. 生成车用气瓶使用登记证单据（ JgVehicleInformation JgVehicleInformationEq ）信息
            JgVehicleInformation jgVehicleInformation = this.claimGenVehicleInfoAbout(paramMap, equList, reginParams, isOneSelf);

            // 3. 生成 使用登记证管理表信息（JgUseRegistrationManage ）证变更记录表信息 （JgCertificateChangeRecord）证变更记录对应设备表信息 （JgCertificateChangeRecordEq）
            this.claimGenCertificateManageAndChange(jgVehicleInformation, equList, reginParams, isOneSelf);

            // 4. 修改三环车辆表的认领状态为已认领
            ShCar shCar = ShCar.builder().claimedFlag("1").build();
            shCar.setSequenceNbr(shCarSequenceNbr);
            this.baseMapper.updateById(shCar);
            return records;
        } catch (Exception e) {
            log.error("三环系统数据认领失败，使用登记证代码：{}", paramMap.get("useRegistrationCode"));
            log.error("失败原因：{}", e.getMessage());
            e.printStackTrace();
            handleClaimFailed(records);
            throw new BadRequest("认领时出现异常，请联系管理员！");
        }
    }

    /**
     * 生成使用登记证管理表信息、证变更记录表信息
     *
     * @param jgVehicleInformation 车用气瓶使用登记证单据
     * @param equList              设备集合
     */
    private void claimGenCertificateManageAndChange(JgVehicleInformation jgVehicleInformation, JSONArray equList, ReginParams reginParams, Boolean isOneSelf) {
        AgencyUserModel result = Privilege.agencyUserClient.queryByUserId(RequestContext.getExeUserId()).getResult();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        String actor = isOneSelf ? jgVehicleInformation.getUseUnitName() + "的" + result.getRealName() + "办理了"
                : reginParams.getCompany().getCompanyName() + "的" + reginParams.getUserModel().getRealName() + "认领了原三环系统中原" + jgVehicleInformation.getUseUnitName() + "的设备，并办理了";
        String changeContent = actor + "【" + BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName() + "】，" + "单号【" + jgVehicleInformation.getApplyNo() + "】，申请日期" + simpleDateFormat.format(new Date());

        // 3.1  生成使用登记证管理表信息（JgUseRegistrationManage ）
        Map<String, String> equType = new HashMap<>();
        equType.put("equList", "压力容器");
        equType.put("equListCode", "2000");
        equType.put("equCategory", "气瓶");
        equType.put("equCategoryCode", "2300");
        equType.put("equDefine", "特种气瓶");
        equType.put("equDefineCode", "23T0");
        // 计算总容积
        BigDecimal totalVolume = equList.stream()
                .map(x -> {
                    try {
                        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(x));
                        Object volumeObj = jsonObject.get("singleBottleVolume");
                        if (volumeObj == null || volumeObj.toString().trim().isEmpty()) {
                            return BigDecimal.ZERO;
                        }
                        return new BigDecimal(volumeObj.toString().trim());
                    } catch (Exception e) {
                        log.error("解析单个气瓶容积失败，设备信息: {}", x, e);
                        return BigDecimal.ZERO;
                    }
                })
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        JgUseRegistrationManage registrationManage = JgUseRegistrationManage.builder()
                .equList("压力容器").equListCode("2000")
                .equCategory("气瓶").equCategoryCode("2300")
                .equDefine("特种气瓶").equDefineCode("23T0")
                .useUnitName(jgVehicleInformation.getUseUnitName())
                .useUnitCreditCode(jgVehicleInformation.getUseUnitCreditCode())
                .applyNo(jgVehicleInformation.getApplyNo())
                .receiveCompanyCode(jgVehicleInformation.getReceiveCompanyCode())
                .receiveOrgName(jgVehicleInformation.getReceiveOrgName())
                .auditPassDate(jgVehicleInformation.getAuditPassDate())
                .useRegistrationCode(jgVehicleInformation.getUseRegistrationCode())
                .certificateNo(commonService.generateCertificateNo(equType, new Date(), jgVehicleInformation.getReceiveCompanyCode()))
                .regType(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName())
                .certificateStatus(CertificateStatusEnum.YIDENGJI.getName())
                .regDate(jgVehicleInformation.getRegDate())
                .createUserId(RequestContext.getExeUserId())
                .volume(totalVolume.toPlainString())
                .carNumber(jgVehicleInformation.getCarNumber())
                .createDate(new Date())
                .gasNum(equList.size())
                .registrationType("1".equals(jgVehicleInformation.getRegType()) ? "1" : "0")
                .useUnitAddress(jgVehicleInformation.getUseUnitAddress())
                .manageType("unit")
                .isScrap("0")
                .version(1)
                .build();
        registrationManage.setIsDelete(Boolean.FALSE);
        useRegistrationManageService.save(registrationManage);

        // 3.2 证变更记录表信息 （JgCertificateChangeRecord）
        // 证变更记录表seq
        Long changeRecordSeq = sequence.nextId();
        JgCertificateChangeRecord changeRecord = JgCertificateChangeRecord.builder()
                .applyNo(jgVehicleInformation.getApplyNo())
                .receiveOrgName(jgVehicleInformation.getReceiveOrgName())
                .auditPassDate(jgVehicleInformation.getAuditPassDate())
                .regType(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName())
                .regDate(jgVehicleInformation.getRegDate()).changeContent(changeContent)
                .useRegistrationCode(jgVehicleInformation.getUseRegistrationCode())
                .receiveCompanyCode(jgVehicleInformation.getReceiveCompanyCode())
                .certificateNo(registrationManage.getCertificateNo())
                .useUnitCreditCode(jgVehicleInformation.getUseUnitCreditCode())
                .useUnitName(jgVehicleInformation.getUseUnitName())
                .equCategory("2300")
                // .routePath(Optional.ofNullable(taskV2Model).map(TaskV2Model::getRoutePath).orElse("")) todo
                .build();
        changeRecord.setSequenceNbr(changeRecordSeq);
        certificateChangeRecordService.save(changeRecord);

        // 3.3 证变更记录对应设备表信息 （JgCertificateChangeRecordEq）
        ArrayList<JgCertificateChangeRecordEq> changeRecordEqList = new ArrayList<>();
        equList.forEach(equ -> changeRecordEqList.add(JgCertificateChangeRecordEq.builder()
                .changeRecordId(String.valueOf(changeRecordSeq))
                .equId(JSON.parseObject(JSON.toJSONString(equ)).getString("record"))
                .productCode(JSON.parseObject(JSON.toJSONString(equ)).getString("factoryNum"))
                .build()));
        certificateChangeRecordEqService.saveBatch(changeRecordEqList);
    }


    /**
     * 认领流程-生成设备信息
     *
     * @param equList 设备集合
     * @return 设备records
     */
    public List<String> claimGenEquInfo(String useRegistrationCode, Map<?, ?> paramMap, JSONArray equList, ReginParams reginParams, Boolean isOneSelf) {
        CompanyBo company = reginParams.getCompany();
        List<String> equRecords = new ArrayList<>();
        // 保存设备后 后续业务需要的设备信息
        for (int i = 0; i < equList.size(); i++) {
            JSONObject equObj = equList.getJSONObject(i);
            Date date = new Date();
            // 设备record
            String equRecord = UUID.randomUUID().toString();
            JSONObject equJson = JSON.parseObject(JSON.toJSONString(equObj));
            equJson.put("record", equRecord);
            equObj = equJson;
            // 清除原先的seq
            equObj.remove("sequenceNbr");
            // 使用信息
            IdxBizJgUseInfo useInfo = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgUseInfo.class);
            useInfo.setRecord(equRecord);
            useInfo.setRecDate(date);
            useInfo.setCreateDate(date);
            useInfo.setDataSource("jg_his_sh");
            useInfo.setIsIntoManagement(Boolean.TRUE);
            useInfo.setEquState("1");
            if (isOneSelf) {
                if (CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType())) {
                    useInfo.setUseUnitName(company.getCompanyName().split("_")[1]);
                    useInfo.setUseUnitCreditCode(company.getCompanyCode().split("_")[1]);
                } else {
                    useInfo.setUseUnitName(company.getCompanyName());
                    useInfo.setUseUnitCreditCode(company.getCompanyCode());
                }
            } else {
                useInfo.setUseUnitName((String) paramMap.get("useUnitName"));
                useInfo.setUseUnitCreditCode((String) paramMap.get("useUnitCreditCode"));
            }
            useInfo.setORegUnit((String) paramMap.get("oRegUnit"));
            useInfo.setORegDate((String) paramMap.get("oRegDate"));
            useInfo.setOldUseRegistrationTable(JSON.toJSONString(paramMap.get("oldUseRegistrationTable")));
            useInfo.setOldUseRegistrationCertificate(JSON.toJSONString(paramMap.get("oldUseRegistrationCertificate")));
            useInfo.setUseInnerCode((String) paramMap.get("carNumber"));
            idxBizJgUseInfoService.save(useInfo);

            // 设计信息
            IdxBizJgDesignInfo designInfo = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgDesignInfo.class);
            designInfo.setRecord(equRecord);
            designInfo.setRecDate(date);
            idxBizJgDesignInfoService.save(designInfo);

            // 制造信息
            IdxBizJgFactoryInfo factoryInfo = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgFactoryInfo.class);
            factoryInfo.setRecDate(date);
            factoryInfo.setRecord(equRecord);
            idxBizJgFactoryInfoService.save(factoryInfo);

            // 施工信息
            IdxBizJgConstructionInfo constructionInfo = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgConstructionInfo.class);
            constructionInfo.setRecord(equRecord);
            constructionInfo.setRecDate(date);
            idxBizJgConstructionInfoService.save(constructionInfo);

            // 注册登记信息
            IdxBizJgRegisterInfo registerInfo = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgRegisterInfo.class);
            registerInfo.setRecord(equRecord);
            registerInfo.setRecDate(date);
            registerInfo.setUseOrgCode(useRegistrationCode);
            registerInfo.setWhetherSkidMountedPressureVessel("0");
            registerInfo.setRegisterState(idxBizJgRegisterInfoService.getRegCode());
            idxBizJgRegisterInfoService.save(registerInfo);

            // 监督管理
            IdxBizJgSupervisionInfo supervisionInfo = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgSupervisionInfo.class);
            supervisionInfo.setRecord(equRecord);
            supervisionInfo.setRecDate(date);
            if (!StringUtils.isEmpty(supervisionInfo.getOrgBranchCode())) {
                String[] orgBranchCode = supervisionInfo.getOrgBranchCode().split("_");
                supervisionInfo.setOrgBranchCode(orgBranchCode[0]);
                supervisionInfo.setOrgBranchName(orgBranchCode[1]);
                HashMap<String, Object> parentMessage = (HashMap<String, Object>) Privilege.companyClient.queryByOrgcode(orgBranchCode[0]).getResult();
                // 目前平台返回key为compnay(存在拼写错误)
                CompanyModel parentModel = JSON.parseObject(JSON.toJSONString(parentMessage.get("compnay")), CompanyModel.class);
                supervisionInfo.setCompanyOrgBranchCode(parentModel.getCompanyCode());
            }
            idxBizJgSupervisionInfoService.save(supervisionInfo);

            // 其他信息
            IdxBizJgOtherInfo otherInfo = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgOtherInfo.class);
            otherInfo.setRecord(equRecord);
            otherInfo.setClaimStatus("已认领");
            otherInfo.setRecDate(date);
            // ---生成监管码
            Map<String, Object> map = new HashMap<>();
            String vehicleApanage = (String) paramMap.get("vehicleApanage");
            // 判断是否为西咸
            String isXiXian = XI_XIAN.getCode().equals(vehicleApanage) ? "1" : "0";
            map.put("cityCode", XI_XIAN.getCode().equals(vehicleApanage) ? XIAN_YANG.getCode() : vehicleApanage);
            map.put("isXiXian", isXiXian);
            map.put("equCategory", registerInfo.getEquCategory());
            map.put("countyCode", XI_XIAN.getCode().equals(vehicleApanage) ? XIAN_YANG.getCode() : vehicleApanage);
            ResponseModel<Map<String, Object>> code = tzsServiceFeignClient.createCode(map);
            Map<String, Object> result = code.getResult();
            otherInfo.setSupervisoryCode((String) result.get("superviseCode"));
            idxBizJgOtherInfoService.save(otherInfo);

            // 压力容器技术参数
            IdxBizJgTechParamsVessel vessel = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgTechParamsVessel.class);
            vessel.setRecord(equRecord);
            vessel.setRecDate(date);
            String VIN = ValidationUtil.isEmpty(paramMap.get("identificationCode")) ? "" : (String) paramMap.get("identificationCode");
            vessel.setVin(VIN);
            idxBizJgTechParamsVesselService.save(vessel);

            // 检验检测信息
            IdxBizJgInspectionDetectionInfo inspectionDetectionInfo = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgInspectionDetectionInfo.class);
            inspectionDetectionInfo.setRecord(equRecord);
            inspectionDetectionInfo.setRecDate(date);
            // 检验机构信息
            if (!StringUtils.isEmpty(inspectionDetectionInfo.getInspectOrgName())) {
                String[] inspectOrg = inspectionDetectionInfo.getInspectOrgName().split("_");
                inspectionDetectionInfo.setInspectOrgCode(inspectOrg[0]);
                inspectionDetectionInfo.setInspectOrgName(inspectOrg[1]);
            }
            if (inspectionDetectionInfo.getNextInspectDate() != null) {
                inspectionDetectionInfo.setNextInspectDate(DateUtil.parse(DateUtil.format(inspectionDetectionInfo.getNextInspectDate(), DatePattern.NORM_DATE_PATTERN)));
            }
            idxBizJgInspectionDetectionInfoService.save(inspectionDetectionInfo);

            // 保存es
            idxBizJgRegisterInfoService.saveEsData(equRecord);

            equRecords.add(equRecord);
            // 更新 equList 中的元素
            equList.set(i, equJson);
        }
        eventPublisher.publish(new EquipCreateOrEditEvent(this, BusinessTypeEnum.JG_NEW_EQUIP.name(), new HashSet<>(equRecords), EquipCreateOrEditEvent.EquipType.equip));
        return equRecords;
    }

    /**
     * 生成车用气瓶使用登记证单据
     *
     * @param paramMap 表单信息
     * @param equList  设备集合
     * @return 车用气瓶使用登记证单据
     */
    public JgVehicleInformation claimGenVehicleInfoAbout(Map<?, ?> paramMap, JSONArray equList, ReginParams reginParams, Boolean isOneSelf) {
        // 车用气瓶登记表seq
        Long vehicleInformationSeq = sequence.nextId();
        CompanyBo company = reginParams.getCompany();
        // 申请编号
        ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.SYDJ.getCode(), 1);
        if (!ObjectUtils.isEmpty(listResponseModel) && listResponseModel.getStatus() != HttpStatus.OK.value()) {
            log.error("车用气瓶使用登记申请单单号获取失败！");
            throw new BadRequest("车用气瓶使用登记申请单单号获取失败！");
        }
        String applyNo = listResponseModel.getResult().get(0);

        // 2.1 车用气瓶登记单表
        JgVehicleInformation vehicleInformation = JSON.parseObject(JSON.toJSONString(paramMap), JgVehicleInformation.class);
        vehicleInformation.setSequenceNbr(vehicleInformationSeq);
        vehicleInformation.setApplyNo(applyNo);
        // 使用单位信息
        if (isOneSelf) {
            if (CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType())) {
                vehicleInformation.setUseUnitName(company.getCompanyName().split("_")[1]);
                vehicleInformation.setUseUnitCreditCode(company.getCompanyCode().split("_")[1]);
            } else {
                vehicleInformation.setUseUnitName(company.getCompanyName());
                vehicleInformation.setUseUnitCreditCode(company.getCompanyCode());
            }
        } else {
            vehicleInformation.setUseUnitName((String) paramMap.get("useUnitName"));
            vehicleInformation.setUseUnitCreditCode((String) paramMap.get("useUnitCreditCode"));
        }

        // 接收单位信息
        if (!StringUtils.isEmpty(vehicleInformation.getReceiveOrgCode())) {
            String[] splitReceiveOrgCode = vehicleInformation.getReceiveOrgCode().split("_");
            CompanyModel result = Privilege.companyClient.queryByCompanyCode(splitReceiveOrgCode[0]).getResult();
            vehicleInformation.setReceiveOrgCode(splitReceiveOrgCode[0]);
            vehicleInformation.setReceiveOrgName(splitReceiveOrgCode[1]);
            vehicleInformation.setReceiveCompanyCode(result.getCompanyCode());
        }
        // 检验机构信息
        if (!StringUtils.isEmpty(vehicleInformation.getInspectUnitCreditCode())) {
            String[] splitInspectUnitCreditCode = vehicleInformation.getInspectUnitCreditCode().split("_");
            vehicleInformation.setInspectUnitCreditCode(splitInspectUnitCreditCode[0]);
            vehicleInformation.setInspectUnitName(splitInspectUnitCreditCode[1]);
        }
        // 安装单位信息
        if (!StringUtils.isEmpty(vehicleInformation.getInstallUnitCode())) {
            String[] splitInstallUnitCode = vehicleInformation.getInstallUnitCode().split("_");
            vehicleInformation.setInstallUnitCode(splitInstallUnitCode[0]);
            vehicleInformation.setInstallUnitName(splitInstallUnitCode[1]);
        }
        // 属地监管部门
        if (!StringUtils.isEmpty(vehicleInformation.getOrgBranchCode())) {
            String[] splitOrgBranchCode = vehicleInformation.getOrgBranchCode().split("_");
            vehicleInformation.setOrgBranchCode(splitOrgBranchCode[0]);
            vehicleInformation.setOrgBranchName(splitOrgBranchCode[1]);
        }
        // 安全管理员
        Optional.ofNullable(String.valueOf(paramMap.get("safetyManagerId"))).filter(manager -> manager.contains("_")).map(manager -> manager.split("_")).ifPresent(data -> {
            vehicleInformation.setSafetyManagerId(data[0]);
            vehicleInformation.setSafetyManagerName(data[1]);
        });
        // 产权单位信息
        if (!StringUtils.isEmpty(vehicleInformation.getEstateUnitName())) {
            String[] data = String.valueOf(paramMap.get("estateUnitName")).split("_");
            vehicleInformation.setEstateUnitCreditCode(data[0]);
            vehicleInformation.setEstateUnitName(data[1]);
        }
        // 检验单位
        if (!StringUtils.isEmpty(vehicleInformation.getInspectUnitName())) {
            String[] data = String.valueOf(paramMap.get("inspectUnitName")).split("_");
            vehicleInformation.setInspectUnitCreditCode(data[0]);
            vehicleInformation.setInspectUnitName(data[1]);
        }
        // 其他附件
        if (!ObjectUtils.isEmpty(paramMap.get("otherAccessories"))) {
            vehicleInformation.setOtherAccessories(JSONObject.toJSONString(paramMap.get("otherAccessories")));
        }
        vehicleInformation.setCreateUserId(reginParams.getUserModel().getUserId());
        vehicleInformation.setRegDate(new Date());
        vehicleInformation.setCreateUserName(reginParams.getUserModel().getRealName());
        vehicleInformation.setGasNum(equList.size());
        vehicleInformation.setAuditPassDate(new Date());
        vehicleInformation.setRegType("1");// 历史登记
        vehicleInformation.setStatus(FlowStatusEnum.TO_BE_FINISHED.getName());
        vehicleInformation.setCreateDate(new Date());
//        BigDecimal totalVolume = equList.stream().map(x -> new BigDecimal(String.valueOf(JSON.parseObject(JSON.toJSONString(x)).get("singleBottleVolume"))))
//                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal totalVolume = equList.stream()
                .map(x -> {
                    try {
                        return new BigDecimal(
                                String.valueOf(JSON.parseObject(JSON.toJSONString(x)).get("singleBottleVolume"))
                        );
                    } catch (Exception e) {
                        return BigDecimal.ZERO;
                    }
                })
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        vehicleInformation.setVolume(totalVolume.toPlainString());
        vehicleInformationService.save(vehicleInformation);

        // 2.2 车用气瓶登记单关联设备表
        List<JgVehicleInformationEq> vehicleInformationEqs = new ArrayList<>();
        equList.forEach(equ -> vehicleInformationEqs.add(JgVehicleInformationEq.builder()
                .vehicleId(String.valueOf(vehicleInformationSeq))
                .equId(JSON.parseObject(JSON.toJSONString(equ)).getString("record"))
                .build()));
        vehicleInformationEqService.saveBatch(vehicleInformationEqs);

        return vehicleInformation;
    }

    /**
     * 认领过程中报错，回滚第一步的es数据
     */
    public void handleClaimFailed(List<String> records) {
        esEquipmentCategory.deleteAll(this.buildEquipCategoryData(records));
        esEquipmentDao.deleteAll(this.buildEquipData(records));
    }

    private Iterable<? extends ESEquipmentInfo> buildEquipData(List<String> records) {
        return records.stream().map(record->{
            ESEquipmentInfo esEquipmentInfo = new ESEquipmentInfo();
            esEquipmentInfo.setSEQUENCE_NBR(record);
            return esEquipmentInfo;
        }).collect(Collectors.toList());
    }

    private Iterable<? extends ESEquipmentCategoryDto> buildEquipCategoryData(List<String> records) {
        return records.stream().map(record->{
            ESEquipmentCategoryDto esEquipmentInfo = new ESEquipmentCategoryDto();
            esEquipmentInfo.setSEQUENCE_NBR(record);
            return esEquipmentInfo;
        }).collect(Collectors.toList());
    }
}