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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.constant.SourceConstant;
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.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.TechnologyService;
import com.ruoyi.common.utils.wrapper.IWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


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

    @Autowired
    ProductionProcessesService productionProcessesService;
    @Autowired
    ApplicableProductsService applicableProductsService;
    @Autowired
    ProductInfoService productInfoService;

    @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.get(technologyVo.getId());
                    for (ApplicableProducts applicableProducts : applicableProductsList1) {
                        ProductInfo productInfo = productInfoMap.get(applicableProducts.getProductId());
                        if (ObjectUtil.isNotEmpty(productInfo)) {
                            productNameList.add(productInfo.getName());
                        } 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());
        List<ProductInfo> productInfos = productInfoService.listByIds(productList);
        result.setApplicableProductsList(productInfos);
        //获取工艺线路信息
        List<String> processRouteIds = Arrays.asList(result.getProcessRoute().split(","));
        List<ProductionProcesses> productionProcessesList = productionProcessesService.listByIds(processRouteIds);
        Map<Long, ProductionProcesses> productionProcessesMap = productionProcessesList.stream()
                .collect(Collectors.groupingBy(ProductionProcesses::getId,
                        Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
        //对工艺线路排序必须按照前端提交的顺序排序
        List<ProductionProcesses> newProductionProcessesList = new ArrayList<>();
        for (String processRouteId : processRouteIds) {
            newProductionProcessesList.add(productionProcessesMap.get(Long.parseLong(processRouteId)));
        }
        result.setProcessRouteList(newProductionProcessesList);
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(TechnologyDto technologyDto) {
        String join = String.join(",", technologyDto.getProcessRouteList());
        technologyDto.setProcessRoute(join);
        this.save(technologyDto);
        List<ApplicableProducts> productList = technologyDto.getProductList();
        for (ApplicableProducts applicableProducts : productList) {
            applicableProducts.setTechnologyId(technologyDto.getId());
        }
        applicableProductsService.saveBatch(productList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(TechnologyDto technologyDto) {
        String join = String.join(",", technologyDto.getProcessRouteList());
        technologyDto.setProcessRoute(join);
        this.updateById(technologyDto);
        List<ApplicableProducts> productList = technologyDto.getProductList();
        applicableProductsService.remove(q -> q.eq(ApplicableProducts::getTechnologyId, technologyDto.getId()));
        for (ApplicableProducts applicableProducts : productList) {
            applicableProducts.setTechnologyId(technologyDto.getId());
        }
        applicableProductsService.saveBatch(productList);
    }

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

}
