package com.yeejoin.amos.boot.module.jg.biz.edit.backup;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.entity.IdxBizJgPipelineOperationHist;
import com.yeejoin.amos.boot.module.jg.biz.service.impl.*;
import com.yeejoin.amos.boot.module.ymt.api.entity.*;
import com.yeejoin.amos.boot.module.ymt.api.mapper.SuperviseInfoMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.typroject.tyboot.core.foundation.context.RequestContext;

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

@Component
@RequiredArgsConstructor
@Slf4j
public class EquipBackupHandler {
    private final IdxBizJgPipelineOperationHistServiceImpl pipelineDeleteHistoryService;

    private final IdxBizJgOtherInfoServiceImpl otherInfoService;
    private final IdxBizJgUseInfoServiceImpl useInfoService;
    private final IdxBizJgRegisterInfoServiceImpl registerInfoService;
    private final IdxBizJgSupervisionInfoServiceImpl supervisionInfoService;
    private final IdxBizJgFactoryInfoServiceImpl factoryInfoService;
    private final IdxBizJgConstructionInfoServiceImpl constructionInfoService;
    private final IdxBizJgInspectionDetectionInfoServiceImpl inspectionDetectionInfoService;
    private final ESEquipmentCategory equipmentCategory;
    private final TechParamsBackupService techParamsBackupService;
    private final SuperviseInfoMapper superviseInfoMapper;

    private final static String BACKUP_JSON_KEY_OTHER_INFO = "otherInfo";
    private final static String BACKUP_JSON_KEY_USE_INFO = "useInfo";
    private final static String BACKUP_JSON_KEY_REGISTER_INFO = "registerInfo";
    private final static String BACKUP_JSON_KEY_SUPERVISION_INFO = "supervisionInfo";
    private final static String BACKUP_JSON_KEY_FACTORY_INFO = "factoryInfo";
    private final static String BACKUP_JSON_KEY_CONSTRUCTION_INFO = "constructionInfoList";
    private final static String BACKUP_JSON_KEY_INSPECTION_DETECTION_INFO = "inspectionDetectionInfoList";
    private final static String BACKUP_JSON_KEY_INSPECTION_ES_INFO = "esInfo";
    private final static String BACKUP_JSON_KEY_TECH_PARAM_INFO = "techParamInfo";


    public void backup2Db(String bizType, String bizId, List<String> records) {
        IdxBizJgPipelineOperationHist deleteHistory = pipelineDeleteHistoryService.getOne(new LambdaQueryWrapper<IdxBizJgPipelineOperationHist>().eq(IdxBizJgPipelineOperationHist::getBizType, bizType).eq(IdxBizJgPipelineOperationHist::getBizId, bizId).orderByDesc(IdxBizJgPipelineOperationHist::getVersion).last("limit 1"));
        if (deleteHistory != null) {
            // 后续编辑
            IdxBizJgPipelineOperationHist newHistory = new IdxBizJgPipelineOperationHist();
            BeanUtil.copyProperties(deleteHistory, newHistory);
            newHistory.setBizId(bizId);
            newHistory.setBizType(bizType);
            newHistory.setSequenceNbr(null);
            newHistory.setRecDate(new Date());
            newHistory.setRecUserId(RequestContext.getExeUserId());
            newHistory.setVersion(newHistory.getVersion() + 1);
            newHistory.setOData(this.buildDeleteData(records));
            pipelineDeleteHistoryService.save(newHistory);
        } else {
            // 首次编辑
            IdxBizJgPipelineOperationHist pipelineDeleteHistory = new IdxBizJgPipelineOperationHist();
            pipelineDeleteHistory.setBizType(bizType);
            pipelineDeleteHistory.setBizId(bizId);
            pipelineDeleteHistory.setRecUserId(RequestContext.getExeUserId());
            pipelineDeleteHistory.setRecDate(new Date());
            pipelineDeleteHistory.setOData(this.buildDeleteData(records));
            pipelineDeleteHistory.setVersion(1);
            pipelineDeleteHistoryService.save(pipelineDeleteHistory);
        }
    }

    private String buildDeleteData(List<String> records) {
        List<Map<String, Object>> data = records.stream().map(record -> {
            IdxBizJgRegisterInfo registerInfo = registerInfoService.getOneData(record);
            Map<String, Object> item = new HashMap<>();
            item.put(BACKUP_JSON_KEY_OTHER_INFO, otherInfoService.getOneData(record));
            item.put(BACKUP_JSON_KEY_REGISTER_INFO, registerInfo);
            item.put(BACKUP_JSON_KEY_SUPERVISION_INFO, supervisionInfoService.getOneData(record));
            item.put(BACKUP_JSON_KEY_FACTORY_INFO, factoryInfoService.getOneData(record));
            item.put(BACKUP_JSON_KEY_USE_INFO, useInfoService.getOneData(record));
            // 技术参数
            item.put(BACKUP_JSON_KEY_TECH_PARAM_INFO, this.getTechParamByEquListAndRecord(registerInfo.getEquList(), record));
            // 检验流水数组
            item.put(BACKUP_JSON_KEY_INSPECTION_DETECTION_INFO, this.getInspectList(record));
            // 施工流水
            item.put(BACKUP_JSON_KEY_CONSTRUCTION_INFO, this.getConstructionList(record));
            Optional<ESEquipmentCategoryDto> op = equipmentCategory.findById(record);
            op.ifPresent(e -> item.put(BACKUP_JSON_KEY_INSPECTION_ES_INFO, e));
            return item;
        }).collect(Collectors.toList());
        return JSONObject.toJSONString(data);
    }

    private List<IdxBizJgConstructionInfo> getConstructionList(String record) {
        return constructionInfoService.list(new LambdaQueryWrapper<IdxBizJgConstructionInfo>().eq(IdxBizJgConstructionInfo::getRecord, record));
    }

    private List<IdxBizJgInspectionDetectionInfo> getInspectList(String record) {
        return inspectionDetectionInfoService.list(new LambdaQueryWrapper<IdxBizJgInspectionDetectionInfo>().eq(IdxBizJgInspectionDetectionInfo::getRecord, record));
    }

    private Object getTechParamByEquListAndRecord(String equList, String record) {
        return techParamsBackupService.getTechParams(equList, record);
    }

    /**
     * 在最小版本中恢复数据
     *
     * @param bizType 业务类型
     * @param bizId   业务唯一标识
     * @return 是否存在编辑记录-存在则恢复
     */
    public Boolean restoreFormBackup(String bizType, String bizId) {
        List<IdxBizJgPipelineOperationHist> opHisList = pipelineDeleteHistoryService.list(new LambdaQueryWrapper<IdxBizJgPipelineOperationHist>()
                .eq(IdxBizJgPipelineOperationHist::getBizType, bizType)
                .eq(IdxBizJgPipelineOperationHist::getBizId, bizId).orderByAsc(IdxBizJgPipelineOperationHist::getVersion));

        if (!opHisList.isEmpty()) {
            // 按照最小的版本恢复数据
            IdxBizJgPipelineOperationHist operationHist = opHisList.get(0);
            Optional.ofNullable(operationHist.getOData()).ifPresent(oData -> {
                List<JSONObject> deleteEqs = JSONObject.parseArray(operationHist.getOData(), JSONObject.class);
                deleteEqs.forEach(eq -> {
                    IdxBizJgOtherInfo otherInfo = JSONObject.parseObject(eq.getString(BACKUP_JSON_KEY_OTHER_INFO), IdxBizJgOtherInfo.class);
                    IdxBizJgRegisterInfo registerInfo = JSONObject.parseObject(eq.getString(BACKUP_JSON_KEY_REGISTER_INFO), IdxBizJgRegisterInfo.class);
                    IdxBizJgSupervisionInfo supervisionInfo = JSONObject.parseObject(eq.getString(BACKUP_JSON_KEY_SUPERVISION_INFO), IdxBizJgSupervisionInfo.class);
                    IdxBizJgFactoryInfo factoryInfo = JSONObject.parseObject(eq.getString(BACKUP_JSON_KEY_FACTORY_INFO), IdxBizJgFactoryInfo.class);
                    IdxBizJgUseInfo useInfo = JSONObject.parseObject(eq.getString(BACKUP_JSON_KEY_USE_INFO), IdxBizJgUseInfo.class);
                    otherInfoService.saveOrUpdate(otherInfo);
                    registerInfoService.saveOrUpdate(registerInfo);
                    supervisionInfoService.saveOrUpdate(supervisionInfo);
                    factoryInfoService.saveOrUpdate(factoryInfo);
                    useInfoService.saveOrUpdate(useInfo);
                    // 检验流水
                    List<IdxBizJgInspectionDetectionInfo> inspectionDetectionInfos = JSONObject.parseArray(eq.getString(BACKUP_JSON_KEY_INSPECTION_DETECTION_INFO), IdxBizJgInspectionDetectionInfo.class);
                    if (!inspectionDetectionInfos.isEmpty()) {
                        inspectionDetectionInfoService.saveOrUpdateBatch(inspectionDetectionInfos);
                    }
                    // 施工流水
                    List<IdxBizJgConstructionInfo> constructionInfoList = JSONObject.parseArray(eq.getString(BACKUP_JSON_KEY_CONSTRUCTION_INFO), IdxBizJgConstructionInfo.class);
                    if (!constructionInfoList.isEmpty()) {
                        constructionInfoService.saveOrUpdateBatch(constructionInfoList);
                    }
                    // 技术参数
                    techParamsBackupService.save(registerInfo.getEquList(), eq.getString(BACKUP_JSON_KEY_TECH_PARAM_INFO));
                    // 设备es数据-兼容有数据没es的脏数据
                    Optional.ofNullable(eq.getString(BACKUP_JSON_KEY_INSPECTION_ES_INFO)).ifPresent(v->equipmentCategory.save(JSONObject.parseObject(v, ESEquipmentCategoryDto.class)));
                });
            });
            // insert的删除
            List<String> insertIds = opHisList.stream().flatMap(o -> o.getInsertPipelines().stream()).collect(Collectors.toList());
            insertIds.remove(null);
            insertIds.remove("");
            if (!insertIds.isEmpty()) {
                superviseInfoMapper.deleteDataAll(insertIds);
            }
        } else {
            log.warn("暂无编辑历史无法恢复数据：{}，{}", bizType, bizId);
        }
         return !opHisList.isEmpty();
    }

    public void updateOperateRecords(String bizId, String bizType, List<String> insertRecord, List<String> deleteRecords) {
        IdxBizJgPipelineOperationHist operationHist = pipelineDeleteHistoryService.getOne(new LambdaQueryWrapper<IdxBizJgPipelineOperationHist>().eq(IdxBizJgPipelineOperationHist::getBizType, bizType).eq(IdxBizJgPipelineOperationHist::getBizId, bizId).orderByDesc(IdxBizJgPipelineOperationHist::getVersion).last("limit 1"));
        if (operationHist != null) {
            operationHist.setInsertPipelines(insertRecord);
            operationHist.setDeletedPipelines(deleteRecords);
            pipelineDeleteHistoryService.updateById(operationHist);
        }
    }

    public List<IdxBizJgPipelineOperationHist> listAllBackupOfOneBizId(String bizType, String bizId) {
        return pipelineDeleteHistoryService.list(new LambdaQueryWrapper<IdxBizJgPipelineOperationHist>()
                .eq(IdxBizJgPipelineOperationHist::getBizType, bizType)
                .eq(IdxBizJgPipelineOperationHist::getBizId, bizId).orderByAsc(IdxBizJgPipelineOperationHist::getVersion));
    }
}
