package com.ximai.mes.pro.controller.task;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ximai.common.annotation.Log;
import com.ximai.common.core.controller.BaseController;
import com.ximai.common.core.domain.AjaxResult;
import com.ximai.common.core.page.TableDataInfo;
import com.ximai.common.enums.BusinessType;
import com.ximai.common.exception.ServiceException;
import com.ximai.common.utils.MessageUtils;
import com.ximai.common.utils.data.ExceptionUtil;
import com.ximai.common.utils.data.StringUtils;
import com.ximai.mes.constant.TmToolMachineCheckEnum;
import com.ximai.mes.constant.TmToolMachineTypeEnum;
import com.ximai.mes.pro.domain.GanttTask;
import com.ximai.mes.pro.domain.proWorkOrder.ProWorkorder;
import com.ximai.mes.pro.domain.task.ProTask;
import com.ximai.mes.pro.domain.task.ProTaskWorkunit;
import com.ximai.mes.pro.domain.task.WorkorderScheduleParams;
import com.ximai.mes.pro.domain.vo.ProTaskVo;
import com.ximai.mes.pro.mapper.task.ProTaskMapper;
import com.ximai.mes.pro.service.proWorkOrder.IProWorkorderService;
import com.ximai.mes.pro.service.task.IProTaskService;
import com.ximai.mes.pro.service.task.IProTaskWorkunitService;
import com.ximai.mes.tm.domain.TmToolMachines;
import com.ximai.mes.tm.domain.vo.TmToolRequestItemVo;
import com.ximai.mes.tm.service.ITmToolMachinesRecordService;
import com.ximai.mes.tm.service.ITmToolMachinesService;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 生产任务Controller
 *
 * @date 2022-05-14
 */
@Slf4j
@RestController
@RequestMapping("/mes/pro/protask")
public class ProTaskController extends BaseController {
    @Autowired
    private IProTaskService proTaskService;

    @Autowired
    private ProTaskMapper proTaskMapper;

    @Autowired
    private IProTaskWorkunitService proTaskWorkunitService;

    @Autowired
    private ITmToolMachinesService tmToolMachinesService;

    @Autowired
    private IProWorkorderService proWorkorderService;

    private ITmToolMachinesRecordService tmToolMachinesRecordService;

    /**
     * 查询生产任务列表
     */
    @GetMapping("/list")
    public TableDataInfo list(ProTask proTask) {
        startPage();
        List<ProTask> list = proTaskService.selectProTaskList(proTask);
        return getDataTable(list);
    }


    /**
     * 查询领料申请的任务信息弹窗
     */
    @GetMapping("/lists")
    public TableDataInfo lists(ProTask proTask) {
        startPage();
        QueryWrapper<ProTask> query = new QueryWrapper<>();
        query.eq(proTask.getWorkstationCode() != null, "ws.workstation_code", proTask.getWorkstationCode());
        query.eq(proTask.getTaskCode() != null, "t.task_code", proTask.getTaskCode());
        query.eq(proTask.getArrangeCode() != null, "t.arrange_code", proTask.getArrangeCode());
        List<ProTask> list = proTaskMapper.selectProTaskLists(query);
        return getDataTable(list);
    }


    /**
     * 获取生产任务的模板信息
     */
    @GetMapping(value = "/getToolInProcess/{taskWorkUnitId}")
    public AjaxResult getToolInProcess(@PathVariable("taskWorkUnitId") Long id) {
        ProTaskWorkunit proTaskWorkunit = proTaskWorkunitService.selectProTaskWorkunitByTaskWorkunitId(id);
        ExceptionUtil.checkTrueThrowException(proTaskWorkunit == null, MessageUtils.message("pro.schedule.data.not.exists"));

        TmToolMachineCheckEnum b = tmToolMachinesService.checkWhetherTheToolTemplateIsSatisfied(id);
        log.info(b.getMsg() + ",taskWorkunitId:" + id);
        if (Objects.equals(b.getStatus(), TmToolMachineCheckEnum.ERROR_06.getStatus())
                || Objects.equals(b.getStatus(), TmToolMachineCheckEnum.NOMAL_00.getStatus())) {
            return AjaxResult.success();
        } else {
            return AjaxResult.error(b.getMsg());
        }
    }


    /**
     * 获取生产任务的模板信息
     */
    @GetMapping(value = "/getToolInProcessTest/{taskWorkUnitId}")
    public AjaxResult getToolInProcessTest(@PathVariable("taskWorkUnitId") Long id) {

        if (id == 1) {
            return AjaxResult.error(MessageUtils.message("pro.tool.error.error_1"));
        }

        if (id == 2) {
            throw new ServiceException(MessageUtils.message("pro.tool.error.error_1"));
        }

        if (id == 3) {
            throw new RuntimeException(MessageUtils.message("pro.tool.error.error_1"));
        }

        return AjaxResult.success();
    }

    /**
     * 获取生产任务的模板信息
     */
    @GetMapping(value = "/getToolOnUseTemplate/{taskWorkunitId}")
    public AjaxResult getToolOnUseTemplate(@PathVariable("taskWorkunitId") Long id) {
        ProTaskWorkunit proTaskWorkunit = proTaskWorkunitService.selectProTaskWorkunitByTaskWorkunitId(id);
        List<TmToolRequestItemVo> toolOnProcessTemplateList = proTaskService.getToolOnProcessTemplate(proTaskWorkunit);
        TmToolMachines tmToolMachines = new TmToolMachines();
        tmToolMachines.setTaskWorkunitId(id);
        List<TmToolMachines> recordsByProcessIdAndArrangeCode = tmToolMachinesService.getRecordsByProcessIdAndArrangeCode(tmToolMachines);
        if (toolOnProcessTemplateList == null) {
            return AjaxResult.success();
        }

        for (TmToolRequestItemVo map : toolOnProcessTemplateList) {
            Long itemId = map.getItemId();
            for (TmToolMachines toolMachines : recordsByProcessIdAndArrangeCode) {
                if (toolMachines.getItemId().equals(itemId) && toolMachines.getType().equals(TmToolMachineTypeEnum.MOUNT.getType())) {
                    map.setAllQuantity(map.getAllQuantity() - 1);
                }
            }
        }
        return AjaxResult.success(toolOnProcessTemplateList.stream().filter(x -> x.getAllQuantity() > 0).collect(Collectors.toList()));
    }


    /**
     * 查询生产任务列表
     */
    @GetMapping("/listDetail")
    public TableDataInfo listDetail(ProTask proTask) {
        startPage();
        List<ProTask> list = proTaskService.selectProTaskDetailList(proTask);
        return getDataTable(list);
    }


    /**
     * 获取生产任务的模板信息
     */
    @GetMapping(value = "/listMdItemByWorkUnit/{taskId}")
    public AjaxResult getMdItemByWorkUnit(@PathVariable("taskId") Long id) {
        return AjaxResult.success(proTaskService.listMdItemByWorkUnit(id));
    }


    /**
     * 获取生产任务详细信息
     */
    @PreAuthorize("@ss.hasPermi('mes:pro:protask:query')")
    @GetMapping(value = "/{taskId}")
    public AjaxResult getInfo(@PathVariable("taskId") Long taskId) {
        ProTaskVo proTaskVo = new ProTaskVo();
        ProTask proTask = proTaskService.selectProTaskByTaskId(taskId);
        if (StringUtils.isNotNull(proTask)) {
            BeanUtils.copyProperties(proTask, proTaskVo);
        }
        return AjaxResult.success(proTaskVo);
    }

    /**
     * 获取甘特图中需要显示的TASK，包括三种类型的内容：
     * 1.Project：基于时间范围搜索的生产工单转换而来的Project。
     * 搜索逻辑为：默认使用当前日期作为开始时间，搜索所有需求时间大于当前时间的生产工单
     * 2.Task：基于生产工单拆分到具体工作站后的生产任务转换而来的Task。
     * 3.Link：根据工序与工序之间的依赖关系转换而来的Link。
     */
    @PreAuthorize("@ss.hasPermi('mes:pro:protask:list')")
    @GetMapping("/listGanttTaskList")
    public AjaxResult getGanttTaskList(ProWorkorder proWorkorder) {
        GanttTask ganttTask = proTaskService.getGanttTaskList();
        return AjaxResult.success(ganttTask);
    }


    /**
     * 新增生产任务
     */
    @PreAuthorize("@ss.hasPermi('mes:pro:protask:add')")
    @Log(title = "生产任务", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody ProTask proTask) {
        return toAjax(proTaskService.createProTask(proTask));
    }

    /**
     * 修改生产任务
     */
    @PreAuthorize("@ss.hasPermi('mes:pro:protask:edit')")
    @Log(title = "生产任务", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody ProTaskVo proTaskVo) {
        // 数据校验
        if (!StringUtils.isNotNull(proTaskVo.getStartTime())) {
            return AjaxResult.error(MessageUtils.message("pro.schedule.error.not.null.startTime"));
        }
        if (!StringUtils.isNotNull(proTaskVo.getDuration())) {
            if (proTaskVo.getDuration() <= 0L) {
                return AjaxResult.error(MessageUtils.message("pro.schedule.limit.min.duration"));
            }
            return AjaxResult.error(MessageUtils.message("pro.schedule.error.not.null.duration"));
        }
        if (!StringUtils.isNotNull(proTaskVo.getWorkunitId())) {
            return AjaxResult.error(MessageUtils.message("md.workUnit.error.not.null"));
        }
        if (proTaskVo.getQuantity().compareTo(BigDecimal.ZERO) != 1) {
            return AjaxResult.error(MessageUtils.message("pro.schedule.limit.min.quantity"));
        }

        proTaskService.manualSchedule(proTaskVo);
        return AjaxResult.success();
    }


    /**
     * 修改生产任务
     */
    @Log(title = "作业分派", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/split")
    public AjaxResult taskWorkunitSplit(@RequestBody ProTaskVo proTaskVo) {
        // 数据校验
        ExceptionUtil.checkTrueThrowException(StringUtils.isNull(proTaskVo.getScheduleStartDate()), MessageUtils.message("pro.schedule.error.not.null.startTime"));
        ExceptionUtil.checkTrueThrowException(StringUtils.isNull(proTaskVo.getDuration()) || proTaskVo.getDuration() <= 0L, MessageUtils.message("pro.schedule.limit.min.duration"));
        ExceptionUtil.checkTrueThrowException(StringUtils.isNull(proTaskVo.getWorkunitId()), MessageUtils.message("md.workUnit.error.not.null"));
        ExceptionUtil.checkTrueThrowException(proTaskVo.getQuantity().compareTo(BigDecimal.ZERO) != 1, MessageUtils.message("pro.schedule.limit.min.quantity"));


        proTaskService.taskWorkunitSplit(proTaskVo);
        return AjaxResult.success();
    }

    /**
     * 删除生产任务
     */
    @PreAuthorize("@ss.hasPermi('mes:pro:protask:remove')")
    @Log(title = "生产任务", businessType = BusinessType.DELETE)
    @DeleteMapping("/{taskIds}")
    public AjaxResult remove(@PathVariable Long[] taskIds) {
        return toAjax(proTaskService.deleteProTaskByTaskIds(taskIds));
    }

    /**
     * 工单合并生成任务单 & 任务单新增
     */
    @PreAuthorize("@ss.hasPermi('mes:pro:protask:add')")
    @Log(title = "生产任务", businessType = BusinessType.INSERT)
    @PostMapping("/{workorderIds}")
    public AjaxResult add(@PathVariable Long[] workorderIds) {
        int i = proTaskService.insertProTasks(workorderIds);

        switch (i) {
            case 0:
                return AjaxResult.error(MessageUtils.message("pro.workOrder.error.error1"));
            case 2:
                return AjaxResult.error(MessageUtils.message("pro.workOrder.error.not.null.process.solution"));
            case 3:
                return AjaxResult.error(MessageUtils.message("pro.workOrder.error.canNot.merge"));
            case 4:
                return AjaxResult.error(MessageUtils.message("pro.workOrder.error.not.exist"));
            case 5:
                return AjaxResult.error(MessageUtils.message("pro.workOrder.error.limit.min.quantity"));
            case 6:
                return AjaxResult.error(MessageUtils.message("pro.schedule.limit.min.quantity"));
            case 7:
                return AjaxResult.error(MessageUtils.message("pro.workOrder.error.error2"));
            case 8:
                return AjaxResult.error(MessageUtils.message("pro.workOrder.error.error3"));
            case 9:
                return AjaxResult.error(MessageUtils.message(MessageUtils.message("pro.workOrder.error.not.null.requestDate")));
            default:
                break;
        }
        return toAjax(i);
    }

    @ApiOperation("生产任务排产")
    @PreAuthorize("@ss.hasPermi('mes:pro:protask:schedule')")
    @Log(title = "生产任务排产", businessType = BusinessType.OTHER)
    @PostMapping("/schedule")
    public AjaxResult schedule(@ApiParam(value = "工单属性集合", required = true) @RequestBody List<WorkorderScheduleParams> params) {
        params.forEach(s->{
            if(s.getScheduleQuantity().compareTo(BigDecimal.ZERO)<=0){
                throw new ServiceException(MessageUtils.message("pro.schedule.limit.min.quantity"));
            }
        });
        proTaskService.schedule(params);
        return AjaxResult.success();
    }


}

