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

import cn.hutool.core.util.ObjectUtil;
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.service.product.ProductInfoService;
import com.fjhx.mes.entity.production.dto.ProductionSchedulingDto;
import com.fjhx.mes.entity.production.dto.ProductionSchedulingSelectDto;
import com.fjhx.mes.entity.production.po.ProductionOrder;
import com.fjhx.mes.entity.production.po.ProductionScheduling;
import com.fjhx.mes.entity.production.vo.ProductionOrderDetailVo;
import com.fjhx.mes.entity.production.vo.ProductionSchedulingVo;
import com.fjhx.mes.mapper.production.ProductionSchedulingMapper;
import com.fjhx.mes.service.production.ProductionSchedulingService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.wrapper.IWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 生产排程 服务实现类
 * </p>
 *
 * @since 2024-02-03
 */
@Service
public class ProductionSchedulingServiceImpl extends ServiceImpl<ProductionSchedulingMapper, ProductionScheduling> implements ProductionSchedulingService {

    private final ProductInfoService productInfoService;

    @Autowired
    public ProductionSchedulingServiceImpl(ProductInfoService productInfoService) {
        this.productInfoService = productInfoService;
    }

    @Override
    public Page<ProductionSchedulingVo> getPage(ProductionSchedulingSelectDto dto) {
        IWrapper<ProductionScheduling> wrapper = getWrapper();
        //只显示投产的数据
        wrapper.isNotNull("po.produce_time");
        //工序id过滤
        wrapper.eq(ProductionScheduling::getProcessesId, dto.getProcessesId());

        //权限过滤：生产排程-1
        wrapper.in("po", ProductionOrder::getCompanyId, SecurityUtils.getCompanyIds());
        wrapper.eq("po", ProductionOrder::getCompanyId, dto.getCompanyId());

        //排程日期过滤
        wrapper.eq("ps", ProductionScheduling::getSchedulingDate, dto.getSchedulingDate());

        wrapper.orderByDesc("ps.scheduling_date");

        Page<ProductionSchedulingVo> page = baseMapper.getPage(dto.getPage(), wrapper);
        List<ProductionSchedulingVo> records = page.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return page;
        }
        //赋值产品信息
        productInfoService.attributeAssign(records, ProductionSchedulingVo::getProductId, (item, productInfo) -> {
            item.setProductName(productInfo.getName());
            item.setProductCode(productInfo.getCustomCode());
            item.setProductLength(productInfo.getLength());
            item.setProductWidth(productInfo.getWidth());
            item.setProductHeight(productInfo.getHeight());
            item.setProductColor(productInfo.getColor());
        });
        return page;
    }

    @Override
    public Map<String, List<ProductionSchedulingVo>> listMap(ProductionSchedulingSelectDto dto) {
        IWrapper<ProductionScheduling> wrapper = getWrapper();
        //权限过滤：生产排程统计
        wrapper.in("ps", ProductionScheduling::getCompanyId, SecurityUtils.getCompanyIds());
        wrapper.eq("ps", ProductionScheduling::getCompanyId, dto.getCompanyId());

        //数据分组
        wrapper.groupBy("ps.scheduling_date", "ps.processes_id");
        //时间范围过滤
        wrapper.ge("ps", ProductionScheduling::getSchedulingDate, dto.getBeginTime());
        wrapper.le("ps", ProductionScheduling::getSchedulingDate, dto.getEndTime());
        //排序
        wrapper.orderByAsc("ps", ProductionScheduling::getSchedulingDate);
        List<ProductionSchedulingVo> list = this.baseMapper.listSumQuantity(wrapper);
        return list.stream().collect(Collectors.groupingBy(ProductionSchedulingVo::getSchedulingDateStr));
    }

    @DSTransactional
    @Override
    public void add(List<ProductionScheduling> dtoList) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (ProductionScheduling dto : dtoList) {
            dto.setCompanyId(SecurityUtils.getCompanyId());

            long count = this.count(q -> q
                    .eq(ProductionScheduling::getTaskId, dto.getTaskId())
                    .eq(ProductionScheduling::getProcessesId, dto.getProcessesId())
                    .eq(ProductionScheduling::getSchedulingDate, dto.getSchedulingDate())
            );
            if (count > 0) {
                throw new ServiceException(sdf.format(dto.getSchedulingDate()) + "已有排程信息，请前往修改或删除！");
            }
        }
        this.saveBatch(dtoList);
    }

    @Override
    public void edit(ProductionSchedulingDto dto) {
        ProductionScheduling oldPs = this.getById(dto.getId());
        Assert.notEmpty(oldPs, "查询不到排程信息！");

        if (dto.getQuantity() < oldPs.getFinishQuantity()) {
            throw new ServiceException("排程数量不能小于已完工数量！");
        }

        this.updateById(dto);
    }

    @Override
    public void delete(Long id) {
        ProductionScheduling oldPs = this.getById(id);
        Assert.notEmpty(oldPs, "查询不到排程信息！");

        if (oldPs.getFinishQuantity() > 0) {
            throw new ServiceException("该排程已有完工信息，禁止删除！");
        }

        this.removeById(id);
    }

    @Override
    public List<ProductionOrderDetailVo> schedulingTaskList() {
        IWrapper<Object> wrapper = IWrapper.getWrapper();
        //获取当天排程的任务
        wrapper.eq("DATEDIFF( now(), ps.scheduling_date )", 0);
        wrapper.groupBy("pod.id");
        List<ProductionOrderDetailVo> voList = baseMapper.schedulingTaskList(wrapper);

        //赋值产品信息
        productInfoService.attributeAssign(voList, ProductionOrderDetailVo::getProductId, (item, productInfo) -> {
            item.setProductName(productInfo.getName());
            item.setProductCode(productInfo.getCustomCode());
            item.setProductLength(productInfo.getLength());
            item.setProductWidth(productInfo.getWidth());
            item.setProductHeight(productInfo.getHeight());
            item.setProductColor(productInfo.getColor());
        });

        //赋值任务信息

        return voList;
    }

}
