package cn.iocoder.yudao.module.mes.controller.admin.task;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.task.vo.TaskPlanParam;
import cn.iocoder.yudao.module.mes.dal.dataobject.plan.PlanDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.task.TaskDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.task.TaskDetailDO;
import cn.iocoder.yudao.module.mes.dal.mysql.plan.PlanMapper;
import cn.iocoder.yudao.module.mes.service.bom.BomService;
import cn.iocoder.yudao.module.mes.service.itemrequisition.ItemAnalysisService;
import cn.iocoder.yudao.module.mes.service.itemrequisition.entity.ItemRequisitionAndStock;
import cn.iocoder.yudao.module.mes.service.plan.PlanService;
import cn.iocoder.yudao.module.mes.service.task.TaskService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

@Tag(name = "管理后台 - 生产任务单")
@RestController
@RequestMapping("/mes/task")
@Validated
public class TaskItemNeedController {

    @Resource
    private TaskService taskService;
    @Resource
    private PlanService planService;
    @Resource
    private PlanMapper planMapper;
    @Resource
    private ErpProductService productService;
    @Resource
    private BomService bomService;
    @Resource
    private ItemAnalysisService itemAnalysisService;

    @GetMapping("/item-need/order")
    @Operation(summary = "获得某订单所需物料数量")
    @Parameter(name = "orderId", description = "订单编号", required = true)
    public CommonResult<List<ItemRequisitionAndStock>> getProductItemNeed(@RequestParam("orderId") Long orderId) {
        List<ItemRequisitionAndStock> list = itemAnalysisService.getItemAnalysis(orderId);
        return success(list);
    }

    @GetMapping("/item-need/task")
    @Operation(summary = "获得生产任务单所需物料")
    @Parameter(name = "taskId", description = "任务编号", required = true)
    public CommonResult<List<ItemRequisitionAndStock>> getTaskItemNeed(@RequestParam("taskId") Long taskId) {
        TaskDO task = taskService.getTask(taskId);
        List<ItemRequisitionAndStock> list = itemAnalysisService.getItemAnalysis(task);
        return success(list);
    }

    @GetMapping("/item-need/plan")
    @Operation(summary = "获得生产计划所需物料")
    @Parameter(name = "planId", description = "计划编号", required = true)
    public CommonResult<List<ItemRequisitionAndStock>> getPlanItemNeed(@RequestParam("planId") Long planId) {
        PlanDO plan = planService.getPlan(planId);
        List<ItemRequisitionAndStock> list = itemAnalysisService.getItemAnalysis(plan);
        return success(list);
    }

    @GetMapping("/item-need/product")
    @Operation(summary = "获得某产品数量所需物料数量")
    @Parameter(name = "productId", description = "任务编号", required = true)
    public CommonResult<List<ItemRequisitionAndStock>> getProductItemNeed(@RequestParam("productId") Long productId,
                                                                          @RequestParam("number") Long number) {
        List<ItemRequisitionAndStock> list = itemAnalysisService.getItemAnalysis(productId, number);
        return success(list);
    }

    /**
     * 对生产任务单进行计划,以每个计划的产品数优先排产ProductsOfPlan
     * 排出的计划数超过选定的天数，则后续计划堆积在最后一天
     **/
    @GetMapping("/generate-plan/byTask")
    @Operation(summary = "对生产任务单进行计划")
    public CommonResult<List<PlanRespVO>> generatePlanByTask(@Valid TaskPlanParam planParam) {
        int sizeOfPlan = 0;
        if(planParam.getPlanDate() != null){
            sizeOfPlan =  planParam.getPlanDate().length;
            //对得到的日期做一下排序，防止拿到的是乱序日期
            Arrays.sort(planParam.getPlanDate(), Comparator.naturalOrder());
        }
        Map<Long, List<PlanDO>> planMap = taskService.generatePlan(planParam.getTaskId(), sizeOfPlan, planParam.getProductsOfPlan());
        List<PlanDO> list = new ArrayList<>();
        //拿到已经存在的计划，排最后面的未完成的计划，看planMap有无同类产品，该产品就排最前
        PlanDO planDO = planService.selectLastOne();
        Long lastProductId = planDO != null ? planDO.getProductId() : 0;
        int dateCount = 0;
        if (lastProductId > 0 && planMap.containsKey(lastProductId)) {
            List<PlanDO> planDOList = planMap.get(lastProductId);
            for (int i = 0; i < planDOList.size(); i++) {
                planDOList.get(i).setPlanEndTime(getNextDate(dateCount, planParam.getPlanDate()));
                planDOList.get(i).setPlanStartTime(getNextDate(dateCount, planParam.getPlanDate()));
                dateCount++;
            }
            list.addAll(planDOList);
        }

        //遍历剩下的产品
        for (Long productId : planMap.keySet()) {
            if (lastProductId > 0 && productId.equals(lastProductId)) continue;
            List<PlanDO> planDOList = planMap.get(productId);
            for (int i = 0; i < planDOList.size(); i++) {
                planDOList.get(i).setPlanEndTime(getNextDate(dateCount, planParam.getPlanDate()));
                planDOList.get(i).setPlanStartTime(getNextDate(dateCount, planParam.getPlanDate()));
                dateCount++;
            }
            list.addAll(planDOList);
        }

        return success(planService.buildVOList(list));
    }

    //根据下标取值返回日期天数，如果下标超出则返回最后一天，如果不给定日期，则默认从今天开始
    private LocalDateTime getNextDate(int index, LocalDateTime[] dateTimes) {
        if (dateTimes == null) return LocalDateTime.now().plusDays(index);
        else if (index >= dateTimes.length) return dateTimes[dateTimes.length - 1];
        else return dateTimes[index];
    }


    /**
     * taskId 为明细id
     * 对生产任务单明细进行计划,以每个计划的产品数优先排产ProductsOfPlan
     * 排出的计划数超过选定的天数，则后续计划堆积在最后一天
     **/
    @GetMapping("/generate-plan/byTaskDetail")
    @Operation(summary = "对生产任务单进行计划")
    public CommonResult<List<PlanRespVO>> generatePlanByTaskDetail(@Valid TaskPlanParam planParam) {
        if(planParam.getPlanDate() != null){
            //对得到的日期做一下排序，防止拿到的是乱序日期
            Arrays.sort(planParam.getPlanDate(), Comparator.naturalOrder());
        }
        TaskDetailDO detailDO = taskService.getTaskDetail(planParam.getTaskDetailId());
        //已经计划数  planMapper.selectSumTaskDetail(detailDO.getId(),null);
        Long number = planParam.getPlanNumber();
        if(number==null)number = detailDO.getNumber();
        //生成计划
        List<PlanDO> planList = taskService.generatePlan3(detailDO.getTaskId(),detailDO.getId(),
                detailDO.getProductId(), number, planParam.getProductsOfPlan());
        //计划排日期
        int dateCount = 0;
        for (int i = 0; i < planList.size(); i++) {
            planList.get(i).setPlanEndTime(getNextDate(dateCount, planParam.getPlanDate()));
            planList.get(i).setPlanStartTime(getNextDate(dateCount, planParam.getPlanDate()));
            dateCount++;
        }
        return success(planService.buildVOList(planList));
    }
}