package com.fjhx.mes.service.technology.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.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.utils.Assert;
import com.fjhx.item.entity.product.po.ProductInfo;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.mes.entity.applicable.po.ApplicableProducts;
import com.fjhx.mes.entity.production.po.ProductionProcesses;
import com.fjhx.mes.entity.technology.dto.TechnologyDto;
import com.fjhx.mes.entity.technology.dto.TechnologySelectDto;
import com.fjhx.mes.entity.technology.po.Technology;
import com.fjhx.mes.entity.technology.po.TechnologyProcessLine;
import com.fjhx.mes.entity.technology.vo.TechnologyVo;
import com.fjhx.mes.mapper.technology.TechnologyMapper;
import com.fjhx.mes.service.applicable.ApplicableProductsService;
import com.fjhx.mes.service.production.ProductionProcessesService;
import com.fjhx.mes.service.technology.TechnologyProcessLineService;
import com.fjhx.mes.service.technology.TechnologyService;
import com.ruoyi.common.utils.wrapper.IWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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


/**
 * <p>
 * 工艺 服务实现类
 * </p>
 *
 * @author
 * @since 2023-03-28
 */
@Service
public class TechnologyServiceImpl extends ServiceImpl<TechnologyMapper, Technology> implements TechnologyService {

    @Autowired
    ProductionProcessesService productionProcessesService;
    @Autowired
    ApplicableProductsService applicableProductsService;
    @Autowired
    ProductInfoService productInfoService;
    @Autowired
    private TechnologyProcessLineService technologyProcessLineService;

    @Override
    public Page<TechnologyVo> getPage(TechnologySelectDto dto) {
        IWrapper<Technology> wrapper = getWrapper();
        wrapper.orderByDesc("t", Technology::getId);
        wrapper.like(Technology::getName, dto.getKeyword());
        Page<TechnologyVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);

        List<TechnologyVo> records = page.getRecords();
        //获取所有适用商品列表
        List<Long> technologyIds = records.stream().map(TechnologyVo::getId).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(technologyIds)) {
            List<ApplicableProducts> applicableProductsList = applicableProductsService.list(q -> q.in(ApplicableProducts::getTechnologyId, technologyIds));
            List<Long> productsIds = applicableProductsList.stream().map(ApplicableProducts::getProductId).collect(Collectors.toList());
            if (ObjectUtil.isNotEmpty(productsIds)) {
                List<ProductInfo> productInfos = productInfoService.listByIds(productsIds);
                Map<Long, ProductInfo> productInfoMap = productInfos.stream().collect(Collectors.groupingBy(ProductInfo::getId, Collectors.collectingAndThen(Collectors.toList(), item -> item.get(0))));
                Map<Long, List<ApplicableProducts>> applicableProductsMap = applicableProductsList.stream().collect(Collectors.groupingBy(ApplicableProducts::getTechnologyId));
                for (TechnologyVo technologyVo : records) {
                    //处理适用产品列表
                    List<String> productNameList = new ArrayList<>();
                    List<ApplicableProducts> applicableProductsList1 = applicableProductsMap.getOrDefault(technologyVo.getId(), new ArrayList<>());
                    for (ApplicableProducts applicableProducts : applicableProductsList1) {
                        ProductInfo productInfo = productInfoMap.get(applicableProducts.getProductId());
                        if (ObjectUtil.isNotEmpty(productInfo)) {
                            productNameList.add(productInfo.getName() + "(" + productInfo.getSpec() + ")");
                        } else {
                            productNameList.add("未知商品:" + applicableProducts.getProductId());
                        }
                    }
                    technologyVo.setApplicableProductsNameList(productNameList);
                }
            }
        }

        //获取所有的工艺线路
        List<String> processRouteIdList = new ArrayList<>();
        List<String> processRoutes = records.stream().map(TechnologyVo::getProcessRoute).collect(Collectors.toList());
        for (String processRoute : processRoutes) {
            if (ObjectUtil.isNotEmpty(processRoute)) {
                List<String> processRouteIds = Arrays.asList(processRoute.split(","));
                processRouteIdList.addAll(processRouteIds);
            }
        }
        if (ObjectUtil.isNotEmpty(processRouteIdList)) {
            //查出所有工序信息
            List<ProductionProcesses> productionProcessesList = productionProcessesService.listByIds(processRouteIdList);
            //根据工序id分组
            Map<Long, ProductionProcesses> productionProcessesMap = productionProcessesList.stream().distinct().collect(Collectors.groupingBy(ProductionProcesses::getId, Collectors.collectingAndThen(Collectors.toList(), item -> item.get(0))));
            for (TechnologyVo technologyVo : records) {
                if (ObjectUtil.isNotEmpty(technologyVo.getProcessRoute())) {
                    List<String> arr = new ArrayList<>();
                    List<String> processRouteIds = Arrays.asList(technologyVo.getProcessRoute().split(","));
                    for (String processRouteId : processRouteIds) {
                        ProductionProcesses productionProcesses = productionProcessesMap.get(Long.parseLong(processRouteId));
                        if (ObjectUtil.isNotEmpty(productionProcesses)) {
                            arr.add(productionProcesses.getName());
                        } else {
                            arr.add("未知工序：" + processRouteId);
                        }
                    }
                    technologyVo.setProcessRouteNameList(arr);
                }
            }
        }
        return page;
    }

    @Override
    public TechnologyVo detail(Long id) {
        Technology technology = this.getById(id);
        TechnologyVo result = BeanUtil.toBean(technology, TechnologyVo.class);
        //获取适用产品信息
        List<ApplicableProducts> list = applicableProductsService.list(q -> q.eq(ApplicableProducts::getTechnologyId, result.getId()));
        List<Long> productList = list.stream().map(ApplicableProducts::getProductId).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(productList)) {
            List<ProductInfo> productInfos = productInfoService.listByIds(productList);
            result.setApplicableProductsList(productInfos);
        } else {
            result.setApplicableProductsList(new ArrayList<>());
        }
        return result;
    }

    @DSTransactional
    @Override
    public void add(TechnologyDto technologyDto) {
        this.save(technologyDto);
        List<ApplicableProducts> productList = technologyDto.getProductList();
        if (ObjectUtil.isNotEmpty(productList)) {
            for (ApplicableProducts applicableProducts : productList) {
                applicableProducts.setTechnologyId(technologyDto.getId());
            }
        }
        applicableProductsService.saveBatch(productList);

        //保存工艺线路列表
        String processRoute;
        List<TechnologyProcessLine> technologyProcessLines = analysisJsonData(technologyDto);
        if (ObjectUtil.isNotEmpty(technologyProcessLines)) {
            technologyProcessLineService.saveBatch(technologyProcessLines);
            List<Long> processLineIds = recursionTechnologyProcessLine(technologyProcessLines, Collections.singletonList(1L));
            processRoute = processLineIds.stream().map(Objects::toString).collect(Collectors.joining(","));
        } else {
            processRoute = null;
        }

        this.update(q -> q.eq(Technology::getId, technologyDto.getId()).set(Technology::getProcessRoute, processRoute));
    }

    @DSTransactional
    @Override
    public void edit(TechnologyDto technologyDto) {
        this.updateById(technologyDto);

        //修改工艺线路列表,只能全删了再创建
        String processRoute;
        technologyProcessLineService.remove(q -> q.eq(TechnologyProcessLine::getTechnologyId, technologyDto.getId()));
        List<TechnologyProcessLine> technologyProcessLines = analysisJsonData(technologyDto);
        if (ObjectUtil.isNotEmpty(technologyProcessLines)) {
            technologyProcessLineService.saveBatch(technologyProcessLines);
            List<Long> processLineIds = recursionTechnologyProcessLine(technologyProcessLines, Collections.singletonList(1L));
            processRoute = processLineIds.stream().map(Objects::toString).collect(Collectors.joining(","));
        } else {
            processRoute = null;
        }

        this.update(q -> q.eq(Technology::getId, technologyDto.getId()).set(Technology::getProcessRoute, processRoute));
    }

    /**
     * 修改工艺适用产品
     */
    @Override
    public void editProduct(TechnologyDto dto) {
        Long technologyId = dto.getId();
        Assert.notEmpty(technologyId, "工艺id不能为空");
        List<ApplicableProducts> productList = dto.getProductList();
        if (ObjectUtil.isEmpty(productList)) {
            productList = new ArrayList<>();
        }
        productList.forEach(item -> item.setTechnologyId(technologyId));
        applicableProductsService.editLinked(productList, ApplicableProducts::getTechnologyId, technologyId);
    }

    /**
     * 遍历工艺线路
     *
     * @return
     */
    private List<Long> recursionTechnologyProcessLine(List<TechnologyProcessLine> technologyProcessLines, List<Long> sourceProcessesIds) {
        List<Long> processIds = new ArrayList<>();

        List<Long> targetProcessesIds = technologyProcessLines.stream()
                .filter(item -> sourceProcessesIds.contains(item.getSourceProcessesId()))
                .map(TechnologyProcessLine::getTargetProcessesId)
                .collect(Collectors.toList());

        if (ObjectUtil.isNotEmpty(targetProcessesIds)) {
            //过滤掉结束节点
            List<Long> collect = targetProcessesIds.stream().filter(item -> !Objects.equals(item, 99L)).collect(Collectors.toList());
            if (ObjectUtil.isNotEmpty(collect)) {
                processIds.addAll(collect);
            }
            processIds.addAll(recursionTechnologyProcessLine(technologyProcessLines, targetProcessesIds));
        }
        //去重
        processIds = processIds.stream().distinct().collect(Collectors.toList());
        return processIds;
    }

    @DSTransactional
    @Override
    public void delete(Long id) {
        this.removeById(id);
        applicableProductsService.remove(q -> q.eq(ApplicableProducts::getTechnologyId, id));
    }

    /**
     * 处理流程图JSON
     */
    private List<TechnologyProcessLine> analysisJsonData(TechnologyDto technologyDto) {
        //读取流程图json信息
        JSONArray nodeObject = JSONArray.parseArray(technologyDto.getNodeObject());
        //遍历信息
        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")) {
                nodeMap.put(json.getString("id"), json);
            }
            //线
            if (shape.equals("edge")) {
                lineList.add(json);
            }
        }

        List<TechnologyProcessLine> 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");

            TechnologyProcessLine technologyProcessLine = new TechnologyProcessLine();
            //读取源节点信息
            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.setTechnologyId(technologyDto.getId());

            technologyProcessLineList.add(technologyProcessLine);
        }

        return technologyProcessLineList;
    }

}
