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

import cn.hutool.core.bean.BeanUtil;
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.List;
import java.util.Map;

/**
 * 批量维护装置及下属管道-策略实现类
 */
@Component
@RequiredArgsConstructor
public class BatchProjectDataEquipChangeProcess 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;
        JSONArray projectContraptions = data.getJSONArray(RequestChangeData.multiDataKey);
        List<ChangeDataDto> allChangeColumns = new ArrayList<>();
        // 装置列表
        List<ProjectContraptionChangeItem> projectContraptionsJavaList = projectContraptions.toJavaList(ProjectContraptionChangeItem.class);
        // 入库前校验
        projectContraptionsJavaList.forEach(item -> {
            Map<String, Object> itemData = item.getDetail();
            if (itemData != null) {
                JSONObject changeJson = (JSONObject) itemData;
                JSONArray equips = changeJson.getJSONArray(RequestChangeData.multiDataKey);
                List<PipelineChangeItemDto> items = equips.toJavaList(PipelineChangeItemDto.class);
                // 1.设备技术参数入库前校验，约束：同一个装置下的管道编号不能重复
                if (items.size() != items.stream().map(TechParamsPipelineChangeFieldDto::getPipelineNumber).distinct().count()) {
                    throw new BadRequest("同一工程装置下管道编号不能重复！");
                }
            }
        });
        // 入库
        projectContraptionsJavaList.forEach(item -> {
            // todo 依赖前端组件
            String projectContraptionId = item.getProjectContraptionId();
            Map<String, Object> itemData = item.getDetail();
            if (itemData != null) {
                JSONObject changeJson = (JSONObject) itemData;
                // 删除的删除--------------------deleteData
                // 新增编辑的管道insert和edit------tableData
                JSONArray insertOrEditPieLines = changeJson.getJSONArray(RequestChangeData.multiDataKey);
                JSONArray deletedPieLines = changeJson.getJSONArray(RequestChangeData.deletedDataKey);
                if(deletedPieLines != null && !deletedPieLines.isEmpty()) {
                    List<PipelineChangeItemDto> deletedPieLinesJavaList = deletedPieLines.toJavaList(PipelineChangeItemDto.class);
                    pieLineDataChangeService.deletePieLineBatch(deletedPieLinesJavaList, allChangeColumns, defaultChangeId);
                }
                List<PipelineChangeItemDto> items = insertOrEditPieLines.toJavaList(PipelineChangeItemDto.class);
                // 1.保存(前端返回的装置信息为大写 需注意)
                ProjectContraptionChangeDataDto projectContraptionChangeDataDto = commonEquipDataProcessService.castMap2Bean(itemData, ProjectContraptionChangeDataDto.class);
                projectContraptionChangeDataDto.setProjectContraptionId(projectContraptionId);
                this.calTotalPieLineLength(projectContraptionChangeDataDto, items);
                pieLineDataChangeService.update(projectContraptionChangeDataDto, allChangeColumns);
                // 2.管道信息入库保存
                items.forEach(it -> {
                    String record = it.getRecord();
                    if(record == null) {    // 新增的管道逻辑
                        pieLineDataChangeService.newPieLine(projectContraptionId, it, allChangeColumns, defaultChangeId);
                    } else {                // 更新逻辑
                        // 设计信息更新
                        pieLineDataChangeService.saveDesignForPieLine(record, allChangeColumns, it);
                        // 技术参数入库保存
                        TechParamsPipelineChangeFieldDto paramsPipelineChangeFieldDto = new TechParamsPipelineChangeFieldDto();
                        BeanUtil.copyProperties(it, 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());
    }

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