package cn.iocoder.yudao.module.mes.dal.mysql.plan;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanPageReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanStatusEnum;
import cn.iocoder.yudao.module.mes.dal.dataobject.plan.PlanDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 生产计划 Mapper
 *
 * @author 内蒙必硕
 */
@Mapper
public interface PlanMapper extends BaseMapperX<PlanDO> {

    default PageResult<PlanDO> selectPage(PlanPageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<PlanDO>()
                .eqIfPresent(PlanDO::getCode, reqVO.getCode())
                .eqIfPresent(PlanDO::getProductId, reqVO.getProductId())
                .eqIfPresent(PlanDO::getTaskDetailId, reqVO.getTaskDetailId())
                .eqIfPresent(PlanDO::getTaskId, reqVO.getTaskId())
                .eqIfPresent(PlanDO::getPlanNumber, reqVO.getPlanNumber())
                .eqIfPresent(PlanDO::getFinishNumber, reqVO.getFinishNumber())
                .eqIfPresent(PlanDO::getStatus, reqVO.getStatus())
                .eqIfPresent(PlanDO::getFeedingPipeline, reqVO.getFeedingPipeline())
                .betweenIfPresent(PlanDO::getPlanStartTime, reqVO.getPlanStartTime())
                .betweenIfPresent(PlanDO::getPlanEndTime, reqVO.getPlanEndTime())
                .betweenIfPresent(PlanDO::getStartTime, reqVO.getStartTime())
                .betweenIfPresent(PlanDO::getEndTime, reqVO.getEndTime())
                .eqIfPresent(PlanDO::getProductionManagerId, reqVO.getProductionManagerId())
                .eqIfPresent(PlanDO::getRemark, reqVO.getRemark())
                .betweenIfPresent(PlanDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(PlanDO::getPriorityNum)
                .orderByDesc(PlanDO::getPlanStartTime)
                .orderByDesc(PlanDO::getPlanEndTime));
    }

    default PlanDO selectByNo(String no) {
        return selectOne(PlanDO::getCode, no);
    }

    default Long selectSum(Long taskId, Long productId, List<Integer> statusList) {
        // SQL sum 查询
        List<Map<String, Object>> result = selectMaps(new QueryWrapper<PlanDO>()
                .select("SUM(plan_number) AS sumCount")
                .in(statusList != null && statusList.size() > 0, "status", statusList)
                .eq(taskId != null, "task_id", taskId)
                .eq(productId != null, "product_id", productId));
        // 获得数量
        if (CollUtil.isEmpty(result)) {
            return 0L;
        }
        return MapUtil.getLong(result.get(0), "sumCount", 0L);
    }

    /**
     * 查询按日期排序最后一个未完成(已经下达)的计划，即更未来远的时间在更近
     **/
    default PlanDO selectLastOne() {
        List<Integer> status = new ArrayList<>();
        status.add(PlanStatusEnum.计划.getValue());
        status.add(PlanStatusEnum.已排产.getValue());
        status.add(PlanStatusEnum.量产.getValue());
        return selectOne(new QueryWrapper<PlanDO>()
                .eq("is_enable", true)
                .in("status", status)
                .orderByDesc("plan_end_time")
                .last("limit 1"));
    }
    default List<PlanDO> selectBy(PlanPageReqVO reqVO) {
        return selectList(new LambdaQueryWrapperX<PlanDO>()
                .eqIfPresent(PlanDO::getProductId, reqVO.getProductId())
                .eqIfPresent(PlanDO::getTaskDetailId, reqVO.getTaskDetailId())
                .eqIfPresent(PlanDO::getTaskId, reqVO.getTaskId())
                .eqIfPresent(PlanDO::getPlanNumber, reqVO.getPlanNumber())
                .eqIfPresent(PlanDO::getFinishNumber, reqVO.getFinishNumber())
                .eqIfPresent(PlanDO::getStatus, reqVO.getStatus())
                .eqIfPresent(PlanDO::getFeedingPipeline, reqVO.getFeedingPipeline())
                .betweenIfPresent(PlanDO::getPlanStartTime, reqVO.getPlanStartTime())
                .betweenIfPresent(PlanDO::getPlanEndTime, reqVO.getPlanEndTime())
                .betweenIfPresent(PlanDO::getStartTime, reqVO.getStartTime())
                .betweenIfPresent(PlanDO::getEndTime, reqVO.getEndTime())
                .eqIfPresent(PlanDO::getProductionManagerId, reqVO.getProductionManagerId())
                .eqIfPresent(PlanDO::getRemark, reqVO.getRemark())
                .betweenIfPresent(PlanDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(PlanDO::getPriorityNum)
                .orderByAsc(PlanDO::getPlanStartTime)
                .orderByAsc(PlanDO::getPlanEndTime));
    }
    default List<PlanDO> selectBy(Long productId,List<Integer> statusList) {
        return selectList(new LambdaQueryWrapperX<PlanDO>()
                .eqIfPresent(PlanDO::getProductId, productId)
                .inIfPresent(PlanDO::getStatus, statusList)
                .orderByDesc(PlanDO::getPriorityNum)
                .orderByDesc(PlanDO::getStartTime));
    }

    //根据产线和状态查询生产计划，按照实际开工时间升序排序，即更早开工的在前面
    default List<PlanDO> selectBy(List<Integer> statusList, String pipeline) {
        return selectList(new LambdaQueryWrapperX<PlanDO>()
                .eqIfPresent(PlanDO::getFeedingPipeline, pipeline)
                .inIfPresent(PlanDO::getStatus, statusList)
                .orderByAsc(PlanDO::getStartTime));
    }
    @Update("UPDATE mes_plan SET status = #{status} WHERE id = #{id}")
    void updateStatus(@Param("id") Long id, @Param("status") Integer status);

    default Long selectSumTaskDetail(Long taskDetailId, List<Integer> statusList) {
        // SQL sum 查询
        List<Map<String, Object>> result = selectMaps(new QueryWrapper<PlanDO>()
                .select("SUM(plan_number) AS sumCount")
                .in(statusList != null && statusList.size() > 0, "status", statusList)
                .eq(taskDetailId != null, "task_detail_id", taskDetailId));
        // 获得数量
        if (CollUtil.isEmpty(result)) {
            return 0L;
        }
        return MapUtil.getLong(result.get(0), "sumCount", 0L);
    }


    default List<PlanDO> getPlanCapacity(List<Integer> statusList, LocalDateTime startTime, LocalDateTime  endTime) {
        return selectList(new LambdaQueryWrapperX<PlanDO>()
                .inIfPresent(PlanDO::getStatus, statusList)
                .betweenIfPresent(PlanDO::getStartTime, startTime, endTime)
                .orderByDesc(PlanDO::getPriorityNum)
                .orderByDesc(PlanDO::getStartTime));
    }

    List<Map<String, Object>> getLastSevenDaysCompletedCount();
}