package com.fjhx.mes.service.work.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.utils.Assert;
import com.fjhx.file.entity.ObsFile;
import com.fjhx.file.utils.ObsFileUtil;
import com.fjhx.mes.entity.applicable.po.ApplicableProducts;
import com.fjhx.mes.entity.production.po.ProductionProcesses;
import com.fjhx.mes.entity.technology.po.Technology;
import com.fjhx.mes.entity.work.dto.WorkOrderProductionProcessesDto;
import com.fjhx.mes.entity.work.po.WorkOrder;
import com.fjhx.mes.entity.work.po.WorkOrderProcessLine;
import com.fjhx.mes.entity.work.po.WorkOrderProductionProcesses;
import com.fjhx.mes.entity.work.vo.WorkOrderProductionProcessesVo;
import com.fjhx.mes.entity.work.vo.WorkOrderVo;
import com.fjhx.mes.mapper.work.WorkOrderProductionProcessesMapper;
import com.fjhx.mes.service.applicable.ApplicableProductsService;
import com.fjhx.mes.service.production.ProductionProcessesService;
import com.fjhx.mes.service.technology.TechnologyService;
import com.fjhx.mes.service.work.WorkOrderProcessLineService;
import com.fjhx.mes.service.work.WorkOrderProductionProcessesService;
import com.fjhx.mes.service.work.WorkOrderService;
import com.ruoyi.common.core.domain.BasePo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 工单工序 服务实现类
 * </p>
 *
 * @author
 * @since 2023-05-17
 */
@Service
public class WorkOrderProductionProcessesServiceImpl extends ServiceImpl<WorkOrderProductionProcessesMapper, WorkOrderProductionProcesses> implements WorkOrderProductionProcessesService {

    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private ProductionProcessesService productionProcessesService;
    @Autowired
    private WorkOrderProcessLineService workOrderProcessLineService;
    @Autowired
    private ApplicableProductsService applicableProductsService;
    @Autowired
    private TechnologyService technologyService;

    @Override
    public WorkOrderVo detail(WorkOrderProductionProcesses dto) {
        WorkOrder workOrder = workOrderService.getById(dto.getWorkOrderId());
        if (ObjectUtil.isEmpty(workOrder)) {
            throw new ServiceException("查询不到工单信息");
        }
        WorkOrderVo workOrderVo = BeanUtil.copyProperties(workOrder, WorkOrderVo.class);

        List<WorkOrderProductionProcesses> workOrderProductionProcessesList = list(q -> q
                .eq(WorkOrderProductionProcesses::getWorkOrderId, dto.getWorkOrderId())
                .orderByAsc(WorkOrderProductionProcesses::getSort));
        //如果定制工序信息为空就获取基础工艺工序信息
        if (ObjectUtil.isEmpty(workOrderProductionProcessesList)) {
            List<ProductionProcesses> productionProcesses = productionProcessesService.getBaseProductionProcessesList(workOrder);
            List<WorkOrderProductionProcessesVo> workOrderProductionProcessesList0 = BeanUtil.copyToList(productionProcesses, WorkOrderProductionProcessesVo.class);
            int i = 0;
            Map<Long,Long> newOldIdMap = new HashMap<>();
            for (WorkOrderProductionProcessesVo workOrderProductionProcesses : workOrderProductionProcessesList0) {
                Long oldId = workOrderProductionProcesses.getId();
                Long newId = IdWorker.getId();
                newOldIdMap.put(oldId,newId);

                workOrderProductionProcesses.setOldId(oldId);//赋值带过来的id
                workOrderProductionProcesses.setId(newId);
                workOrderProductionProcesses.setSort(i);
                i++;
            }
            workOrderVo.setWorkOrderProductionProcessesList(workOrderProductionProcessesList0);

            //赋值工艺JSON
            ApplicableProducts applicableProducts = applicableProductsService.getOne(q -> q
                    .eq(ApplicableProducts::getProductId, workOrderVo.getProductId())
            );
            if(ObjectUtil.isNotEmpty(applicableProducts)){
                Technology technology = technologyService.getById(applicableProducts.getTechnologyId());
                String nodeObject = technology.getNodeObject();

                JSONArray newArray = new JSONArray();

                JSONArray jsonArray = JSONArray.parseArray(nodeObject);
                for (int j = 0; j < jsonArray.size(); j++) {
                    JSONObject json = jsonArray.getJSONObject(j);
                    if(json.getString("shape").equals("handle-btn") || json.getString("shape").equals("handle-btn-one")){
                        Long oldProductionId = json.getLong("productionId");
                        Long newProductionId = newOldIdMap.get(oldProductionId);
                        if(ObjectUtil.isNotEmpty(newProductionId)) {
                            json.put("productionId", newProductionId.toString());
                        }
                    }
                    newArray.add(json);
                }

                workOrderVo.setCustomizedNodeObject(newArray.toString());
            }
            return workOrderVo;
        }
        List<WorkOrderProductionProcessesVo> workOrderProductionProcessesVos = BeanUtil.copyToList(workOrderProductionProcessesList, WorkOrderProductionProcessesVo.class);

        workOrderVo.setWorkOrderProductionProcessesList(workOrderProductionProcessesVos);

        return workOrderVo;
    }

    @DSTransactional
    @Override
    public void edit(WorkOrderProductionProcessesDto dto) {
        workOrderService.update(q -> q
                .eq(WorkOrder::getId, dto.getWorkOrderId())
                .set(ObjectUtil.isNotEmpty(dto.getTechnologyStatus()),WorkOrder::getTechnologyStatus, dto.getTechnologyStatus())
                .set(WorkOrder::getCustomizedNodeObject, dto.getCustomizedNodeObject())
                .set(BasePo::getUpdateTime, new Date())
                .set(BasePo::getUpdateUser, SecurityUtils.getUserId())
        );

        List<WorkOrderProductionProcessesVo> workOrderProductionProcessesList = dto.getWorkOrderProductionProcessesList();

        int i = 0;
        for (WorkOrderProductionProcessesVo workOrderProductionProcesses : workOrderProductionProcessesList) {
            workOrderProductionProcesses.setWorkOrderId(dto.getWorkOrderId());
            workOrderProductionProcesses.setSort(i);
            List<ObsFile> fileList = workOrderProductionProcesses.getFileList();
            if (ObjectUtil.isNotEmpty(fileList)) {
                workOrderProductionProcesses.setFileName(fileList.get(0).getFileName());
            }
            i++;

            this.saveOrUpdate(workOrderProductionProcesses);

            ObsFileUtil.editFile(workOrderProductionProcesses.getFileList(), workOrderProductionProcesses.getId());
        }
        List<WorkOrderProductionProcesses> workOrderProductionProcessesList1 = BeanUtil.copyToList(workOrderProductionProcessesList, WorkOrderProductionProcesses.class);
        this.editLinked(workOrderProductionProcessesList1, WorkOrderProductionProcesses::getWorkOrderId, dto.getWorkOrderId());


        //保存图信息
        WorkOrder workOrder = workOrderService.getById(dto.getWorkOrderId());
        //先删除图信息再保存
        workOrderProcessLineService.remove(q->q.eq(WorkOrderProcessLine::getWorkOrderId,workOrder.getId()));
        List<WorkOrderProcessLine> workOrderProcessLines = analysisJsonData(workOrder);
        if(ObjectUtil.isNotEmpty(workOrderProcessLines)){
            workOrderProcessLineService.saveBatch(workOrderProcessLines);
        }

        //检查定制工单是否配置BOM、工艺 配置完成发消息
        workOrderService.checkWorkOrderStatus(dto.getWorkOrderId());

        //增加附件（绑定到工单上,附件类型为1）
        ObsFileUtil.editFile(dto.getFileList(),dto.getWorkOrderId(),1);
    }

    /**
     * 处理流程图JSON
     */
    private List<WorkOrderProcessLine> analysisJsonData(WorkOrder workOrder) {
        //读取流程图json信息
        JSONArray nodeObject = JSONArray.parseArray(workOrder.getCustomizedNodeObject());
        //遍历信息
        Map<String, JSONObject> nodeMap = new HashMap<>();
        List<JSONObject> lineList = new ArrayList<>();
        for (int i = 0; i < nodeObject.size(); i++) {
            JSONObject json = nodeObject.getJSONObject(i);
            String shape = json.getString("shape");
            //节点
            if (shape.equals("handle-btn") || shape.equals("handle-btn-one")) {
                nodeMap.put(json.getString("id"), json);
            }
            //线
            if (shape.equals("edge")) {
                lineList.add(json);
            }
        }

        List<WorkOrderProcessLine> technologyProcessLineList = new ArrayList<>();

        for (JSONObject jsonObject : lineList) {
            JSONObject source = jsonObject.getJSONObject("source");
            String sourceCell = source.getString("cell");
            JSONObject target = jsonObject.getJSONObject("target");
            String targetCell = target.getString("cell");

            WorkOrderProcessLine technologyProcessLine = new WorkOrderProcessLine();
            //读取源节点信息
            if (sourceCell.equals("1") || sourceCell.equals("99")) {
                technologyProcessLine.setSourceProcessesId(Long.parseLong(sourceCell));
            } else {
                JSONObject from = nodeMap.get(sourceCell);
                Assert.notEmpty(from, "查询不到节点信息：" + sourceCell);
                technologyProcessLine.setSourceProcessesId(from.getLong("productionId"));
            }
            //读取目标节点信息
            if (targetCell.equals("1") || targetCell.equals("99")) {
                technologyProcessLine.setTargetProcessesId(Long.parseLong(targetCell));
            } else {
                JSONObject to = nodeMap.get(targetCell);
                Assert.notEmpty(to, "查询不到节点信息：" + targetCell);
                technologyProcessLine.setTargetProcessesId(to.getLong("productionId"));
            }

            technologyProcessLine.setWorkOrderId(workOrder.getId());

            technologyProcessLineList.add(technologyProcessLine);
        }

        return technologyProcessLineList;
    }

}
