package com.fjhx.service.working.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.base.BaseEntity;
import com.fjhx.entity.product.ProductEx;
import com.fjhx.entity.working.WorkingProcedure;
import com.fjhx.entity.working.WorkingRoute;
import com.fjhx.entity.working.WorkingRouteProcedure;
import com.fjhx.mapper.working.WorkingRouteMapper;
import com.fjhx.params.working.WorkingRouteEx;
import com.fjhx.params.working.WorkingRouteVo;
import com.fjhx.service.product.ProductExService;
import com.fjhx.service.working.WorkingProcedureService;
import com.fjhx.service.working.WorkingRouteProcedureService;
import com.fjhx.service.working.WorkingRouteService;
import com.fjhx.utils.Assert;
import com.fjhx.utils.WrapperUtil;
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.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 工艺路线 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-07-14
 */
@Service
public class WorkingRouteServiceImpl extends ServiceImpl<WorkingRouteMapper, WorkingRoute> implements WorkingRouteService {

    @Autowired
    private WorkingRouteProcedureService workingRouteProcedureService;

    @Autowired
    private WorkingProcedureService workingProcedureService;

    @Autowired
    private ProductExService productExService;

    @Override
    public Page<WorkingRouteEx> getPage(Map<String, String> condition) {

        QueryWrapper<?> wrapper = WrapperUtil.init(condition)
                .keyword("wr.name", "wr.introduce")
                .createTimeDesc("wr")
                .getWrapper();

        wrapper.orderByAsc("wrp.sort");
        wrapper.groupBy("wr.id");

        String keyword = condition.get("keyword");

        wrapper.having(ObjectUtil.isNotEmpty(keyword), "instr( workingProcedureGroup, {0} )> 0 " +
                "OR instr( productGroup, {0} )> 0 ", keyword);

        return baseMapper.getPage(createPage(condition), wrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(WorkingRouteVo workingRouteVo) {
        save(workingRouteVo);

        Long id = workingRouteVo.getId();

        // 工艺路线关联工序
        List<WorkingRouteProcedure> workingProcedureList = workingRouteVo.getWorkingRouteProcedureList();
        if (workingProcedureList.size() > 0) {
            for (int i = 0; i < workingProcedureList.size(); i++) {
                WorkingRouteProcedure workingRouteProcedure = workingProcedureList.get(i);
                workingRouteProcedure.setSort(i);
                workingRouteProcedure.setWorkingRouteId(id);
            }
            workingRouteProcedureService.saveBatch(workingProcedureList);
        }

        // 工艺路线适用产品
        List<Long> productIdList = workingRouteVo.getProductIdList();
        if (productIdList.size() > 0) {
            workingRouteProduct(productIdList, id);
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(WorkingRouteVo workingRouteVo) {
        updateById(workingRouteVo);

        Long id = workingRouteVo.getId();

        Assert.notEmpty(id, "工艺路线id不能为空");

        // 工艺路线关联工序
        List<WorkingRouteProcedure> workingProcedureList = workingRouteVo.getWorkingRouteProcedureList();
        if (workingProcedureList.size() > 0) {
            for (int i = 0; i < workingProcedureList.size(); i++) {
                WorkingRouteProcedure workingRouteProcedure = workingProcedureList.get(i);
                workingRouteProcedure.setSort(i);
                workingRouteProcedure.setWorkingRouteId(id);
            }
            workingRouteProcedureService.saveOrUpdateBatch(workingProcedureList);

            List<Long> workingProcedureIdList = workingProcedureList.stream().map(BaseEntity::getId).collect(Collectors.toList());
            workingRouteProcedureService.remove(Wrappers.<WorkingRouteProcedure>lambdaQuery()
                    .eq(WorkingRouteProcedure::getWorkingRouteId, id)
                    .notIn(workingProcedureIdList.size() > 0, BaseEntity::getId, workingProcedureIdList));
        }

        // 工艺路线适用产品
        List<Long> productIdList = workingRouteVo.getProductIdList();
        if (productIdList.size() > 0) {
            workingRouteProduct(productIdList, id);

            // 去除这个工艺路线已关联的其他产品
            productExService.update(Wrappers.<ProductEx>lambdaUpdate()
                    .eq(ProductEx::getWorkingRouteId, id)
                    .notIn(productIdList.size() > 0, ProductEx::getId, productIdList)
                    .set(ProductEx::getWorkingRouteId, null));
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(WorkingRouteVo workingRouteVo) {
        Long id = workingRouteVo.getId();

        removeById(id);

        // 去除这个工艺路线已关联的产品
        productExService.update(Wrappers.<ProductEx>lambdaUpdate()
                .eq(ProductEx::getWorkingRouteId, id)
                .set(ProductEx::getWorkingRouteId, null));

        // 去除工艺路线关联工序
        workingRouteProcedureService.remove(WorkingRouteProcedure::getWorkingRouteId, id);

    }

    @Override
    public WorkingRouteEx details(WorkingRouteVo workingRouteVo) {
        Long id = workingRouteVo.getId();
        WorkingRoute workingRoute = getById(id);
        WorkingRouteEx result = BeanUtil.toBean(workingRoute, WorkingRouteEx.class);

        List<WorkingRouteProcedure> list = workingRouteProcedureService.lambdaQuery()
                .eq(WorkingRouteProcedure::getWorkingRouteId, id)
                .orderByAsc(WorkingRouteProcedure::getSort)
                .list();


        if (list.size() > 0) {
            List<Long> workingRouteIdList = list.stream().map(WorkingRouteProcedure::getWorkingProcedureId).collect(Collectors.toList());
            Map<Long, WorkingProcedure> kEntity = workingProcedureService.getKEntity(BaseEntity::getId,
                    q -> q.in(BaseEntity::getId, workingRouteIdList));

            List<WorkingProcedure> workingProcedures = new ArrayList<>();

            for (WorkingRouteProcedure workingRouteProcedure : list) {
                WorkingProcedure workingProcedure = kEntity.get(workingRouteProcedure.getWorkingProcedureId());
                if (workingProcedure != null) {
                    workingProcedures.add(workingProcedure);
                }
            }

            result.setWorkingProcedureList(workingProcedures);
        }

        return result;
    }

    /**
     * 产品关联工艺路线
     *
     * @param productIdList  产品id
     * @param workingRouteId 工艺路线id
     */
    private void workingRouteProduct(List<Long> productIdList, Long workingRouteId) {
        List<ProductEx> productExList = productIdList.stream().map(item -> {
            ProductEx productEx = new ProductEx();
            productEx.setId(item);
            productEx.setWorkingRouteId(workingRouteId);
            return productEx;
        }).collect(Collectors.toList());
        productExService.updateBatchById(productExList);
    }

}
