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.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.dto.ESEquipmentCategoryDto;
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.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.IIdxBizJgInspectionDetectionInfoService;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
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.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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 static com.alibaba.fastjson.JSON.toJSONString;

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

    @Resource
    private RedisUtils redisUtils;
    @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 TzsServiceFeignClient tzsServiceFeignClient;
    @Resource
    private JgVehicleInformationServiceImpl vehicleInformationService;
    @Resource
    private JgVehicleInformationEqServiceImpl vehicleInformationEqService;
    @Resource
    private JgUseRegistrationManageServiceImpl useRegistrationManageService;
    @Resource
    private JgCertificateChangeRecordServiceImpl certificateChangeRecordService;
    @Resource
    private JgCertificateChangeRecordEqServiceImpl certificateChangeRecordEqService;
    @Resource
    private CommonServiceImpl commonService;

    private final ShCarMapper shCarMapper;

    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
    @Transactional(rollbackFor = Exception.class)
    public Boolean claim(Map<String, Object> paramMap) {

        // 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")));

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

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

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

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

            // 4. 修改三环车辆表的认领状态为已认领
            ShCar shCar = ShCar.builder().claimedFlag("1").build();
            shCar.setSequenceNbr(shCarSequenceNbr);
            this.baseMapper.updateById(shCar);

            return Boolean.TRUE;

        } catch (Exception e) {
            log.error("三环系统数据认领失败，使用登记证代码：{}", paramMap.get("useRegistrationCode"));
            log.error("失败原因：{}",e.getMessage());
            this.handleClaimFailed(equList);
            throw new BadRequest("认领时出现异常，请联系管理员！");
        }

    }

    /**
     * 生成使用登记证管理表信息、证变更记录表信息
     *
     * @param jgVehicleInformation 车用气瓶使用登记证单据
     * @param equList              设备集合
     */
    private void claimGenCertificateManageAndChange(JgVehicleInformation jgVehicleInformation, JSONArray equList) {
        AgencyUserModel result = Privilege.agencyUserClient.queryByUserId(RequestContext.getExeUserId()).getResult();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        String changeContent = jgVehicleInformation.getUseUnitName() + "的" + result.getRealName() + "办理了【" + 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", "2300");
        equType.put("equCategory", "气瓶");
        equType.put("equCategoryCode", "2300");
        equType.put("equDefine", "特种气瓶");
        equType.put("equDefineCode", "23T0");
        BigDecimal totalVolume = equList.stream().map(x -> new BigDecimal(String.valueOf(JSON.parseObject(JSON.toJSONString(x)).get("singleBottleVolume"))))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        JgUseRegistrationManage registrationManage = JgUseRegistrationManage.builder()
                .equList("压力容器").equListCode("2300")
                .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(String.valueOf(totalVolume))
                .carNumber(jgVehicleInformation.getCarNumber())
                .createDate(new Date())
                .gasNum(equList.size())
                .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 设备集合
     */
    public void claimGenEquInfo(JSONArray equList, ReginParams reginParams) {
        CompanyBo company = reginParams.getCompany();
        // 保存设备后 后续业务需要的设备信息
        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.setDataSource("jg_his_sh");
            useInfo.setIsIntoManagement(Boolean.TRUE);
            useInfo.setEquState("1");
            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());
            }
            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(equObj.getString("useRegistrationCode"));
            registerInfo.setRegisterState(idxBizJgRegisterInfoService.getRegCode());
            idxBizJgRegisterInfoService.save(registerInfo);

            // 监督管理
            IdxBizJgSupervisionInfo supervisionInfo = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgSupervisionInfo.class);
            supervisionInfo.setRecord(equRecord);
            supervisionInfo.setRecDate(date);
            idxBizJgSupervisionInfoService.save(supervisionInfo);

            // 其他信息
            IdxBizJgOtherInfo otherInfo = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgOtherInfo.class);
            otherInfo.setRecord(equRecord);
            otherInfo.setClaimStatus("已认领");
            otherInfo.setRecDate(date);
            idxBizJgOtherInfoService.save(otherInfo);

            // 压力容器技术参数
            IdxBizJgTechParamsVessel vessel = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgTechParamsVessel.class);
            vessel.setRecord(equRecord);
            vessel.setRecDate(date);
            idxBizJgTechParamsVesselService.save(vessel);

            // 检验检测信息
            IdxBizJgInspectionDetectionInfo inspectionDetectionInfo = JSON.parseObject(JSON.toJSONString(equObj), IdxBizJgInspectionDetectionInfo.class);
            inspectionDetectionInfo.setRecord(equRecord);
            inspectionDetectionInfo.setRecDate(date);
            if (inspectionDetectionInfo.getNextInspectDate() != null) {
                inspectionDetectionInfo.setNextInspectDate(DateUtil.parse(DateUtil.format(inspectionDetectionInfo.getNextInspectDate(), DatePattern.NORM_DATE_PATTERN)));
            }
            idxBizJgInspectionDetectionInfoService.save(inspectionDetectionInfo);

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

            // 更新 equList 中的元素
            equList.set(i, equJson);
        }
    }

    /**
     * 生成车用气瓶使用登记证单据
     *
     * @param paramMap 表单信息
     * @param equList  设备集合
     * @return 车用气瓶使用登记证单据
     */
    public JgVehicleInformation claimGenVehicleInfoAbout(Map<String, Object> paramMap, JSONArray equList, ReginParams reginParams) {
        // 车用气瓶登记表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 (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());
        }
        // 接收单位信息
        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 (!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);
        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(JSONArray equList) {
        if (!equList.isEmpty()) {
            equList.forEach(equ -> {
                String record = JSON.parseObject(toJSONString(equ)).getString("record");
                Optional<ESEquipmentCategoryDto> data = esEquipmentCategory.findById(record);
                if (!ObjectUtils.isEmpty(data)) {
                    esEquipmentCategory.deleteById(record);
                }
            });
        }
    }
}