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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.boot.module.jg.api.dto.*;
import com.yeejoin.amos.boot.module.jg.biz.dto.RequestChangeData;
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.IEquipChangeDataProcessStrategy;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

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

/**
 * 单个装置维护-策略实现类
 */
@Component
@RequiredArgsConstructor
public class SingleProjectDataEquipChangeProcess implements IEquipChangeDataProcessStrategy {

    private final CommonEquipDataProcessService commonEquipDataProcessService;

    private final PieLineDataChangeServiceImpl pieLineDataChangeService;


    @Override
    public List<ChangeDataDto> handle(Map<String, Object> changeData, String defaultChangeId) {
        JSONObject data = (JSONObject) changeData;
        // 新增编辑的管道------------------tableData
        JSONArray insertOrEditPieLines = data.getJSONArray(RequestChangeData.multiDataKey);
        // 删除的管道---------------------deleteData
        JSONArray deletedPieLines = data.getJSONArray(RequestChangeData.deletedDataKey);
        List<ChangeDataDto> allChangeColumns = new ArrayList<>();
        List<PipelineChangeItemDto> items = insertOrEditPieLines.toJavaList(PipelineChangeItemDto.class);
        // 1.设备技术参数入库前校验，约束：同一个装置下的管道编号不能重复
        if (items.size() != items.stream().map(TechParamsPipelineChangeFieldDto::getPipelineNumber).distinct().count()) {
            throw new BadRequest("同一工程装置下管道编号不能重复！");
        }
        if(deletedPieLines != null && !deletedPieLines.isEmpty()) {
            List<PipelineChangeItemDto> deletedPieLinesJavaList = deletedPieLines.toJavaList(PipelineChangeItemDto.class);
            pieLineDataChangeService.deletePieLineBatch(deletedPieLinesJavaList, allChangeColumns, defaultChangeId);
        }
        // 2.装置基本信息校验、保存(前端返回的装置信息为大写 需注意)
        ProjectContraptionChangeDataDto projectContraptionChangeDataDto = commonEquipDataProcessService.castMap2Bean(changeData, ProjectContraptionChangeDataDto.class);
        this.calTotalPieLineLength(projectContraptionChangeDataDto, items);
        pieLineDataChangeService.update(projectContraptionChangeDataDto, allChangeColumns);
        // 3.管道信息入库保存
        items.forEach(item -> {
            String record = item.getRecord();
            if(record == null) {    // 新增的管道逻辑
                pieLineDataChangeService.newPieLine(projectContraptionChangeDataDto.getProjectContraptionId(), item, allChangeColumns, defaultChangeId);
            } else {                // 更新逻辑
                // 设计信息更新
                pieLineDataChangeService.saveDesignForPieLine(record, allChangeColumns, item);
                // 技术参数入库保存
                TechParamsPipelineChangeFieldDto paramsPipelineChangeFieldDto = new TechParamsPipelineChangeFieldDto();
                BeanUtil.copyProperties(item, paramsPipelineChangeFieldDto, false);
                commonEquipDataProcessService.savePieLineTechParam(record, allChangeColumns, paramsPipelineChangeFieldDto);
            }
        });
        // 4.更新所有管道的的冗余的管道名称字段（重点注意包括本次没做使用登记的管道也要更新)
        pieLineDataChangeService.updateEs(projectContraptionChangeDataDto);
        return allChangeColumns;
    }

    private void calTotalPieLineLength(ProjectContraptionChangeDataDto projectContraptionChangeDataDto, List<PipelineChangeItemDto> items) {
        projectContraptionChangeDataDto.setPipelineLength(items.stream().filter(i -> i.getPipeLength() != null).mapToDouble(TechParamsPipelineChangeFieldDto::getPipeLength).sum());
    }


    private Map<String, Object> cast2UnderCase(Map<String, Object> re) {
        // 由于历史遗留问题，和前端保存统一，要转成大写下滑线驼峰
        Map<String, Object> result = new HashMap<>();
        re.forEach((k, v) -> {
            result.put(CharSequenceUtil.toUnderlineCase(k).toUpperCase(), v);
        });
        return result;
    }


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