package com.wms.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wms.constants.enums.ConfigMapKeyEnum;
import com.wms.entity.table.Stand;
import com.wms.service.*;
import com.wms.service.business.IWmsJobService;
import com.wms.service.business.IWorkService;
import com.wms.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import static com.wms.config.InitLocalConfig.configMap;
import static com.wms.utils.StringUtils.convertJsonString;

import java.util.*;

/**
 * 定期任务类
 */
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class JobComponent {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * WMS定时任务服务
     */
    private final IWmsJobService wmsJobService;
    /**
     * 站台服务
     */
    private final StandService standService;
    /**
     * 工作服务
     */
    private final IWorkService workService;

    /**
     * 向Wcs下发任务
     * 每2秒执行一次
     */
    @Scheduled(fixedDelay = 2000)
    @Async("myThreadPool")
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    public void sendCommonTasks() {
        String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey());
        if (StringUtils.isEmpty(sendTask) || !sendTask.equals("1")) {
            return;
        }
        try {
            // 发送正常任务
            wmsJobService.sendCommonTasks();
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 向Wcs下发站台拣选出库任务
     * 每2秒执行一次
     */
    @Scheduled(fixedDelay = 2000)
    @Async("myThreadPool")
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    public void sendPickOutTasks() {
        String sendTask = configMap.get(ConfigMapKeyEnum.SEND_PICK_OUT_TASK.getConfigKey());
        if (StringUtils.isEmpty(sendTask) || !sendTask.equals("1")) {
            return;
        }
        try {
            // 发送站台拣选出库任务
            wmsJobService.sendPickOutTasks();
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 拣选任务
     * 每2秒执行一次
     */
    @Scheduled(fixedDelay = 2000)
    @Async("myThreadPool")
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    public void sendPickTasks() {
        String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey());
        if (StringUtils.isEmpty(sendTask) || !sendTask.equals("1")) {
            return;
        }
        try {
            // 发送拣选任务
            wmsJobService.sendPickTasks();
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 重复入库任务
     * 每2秒执行一次
     */
//    @Scheduled(fixedDelay = 2000)
    @Async("myThreadPool")
    @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    public void solveDuplicateTask() {
        String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey());
        if (StringUtils.isEmpty(sendTask) || !sendTask.equals("1")) {
            return;
        }
        try {
            // 针对重复入库的任务，发送新的目的地
            wmsJobService.solveDuplicateTask();
        } catch (Exception e) {
            // 回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 创建工作
     */
    @Scheduled(fixedDelay = 2000)
    public void createWork() {
        String createWork = configMap.get(ConfigMapKeyEnum.CREATE_WORK.getConfigKey());
        if (StringUtils.isEmpty(createWork) || !createWork.equals("1")) {
            return;
        }
        // 轮询工作站台，判断是否需要下发任务
        List<Stand> stands = standService.list(new LambdaQueryWrapper<Stand>()
                .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0)
                .eq(Stand::getStandType, 2));
        for (Stand workStation : stands) {
            try {
                // 创建工作
                workService.createWork(workStation.getStandId());
            } catch (Exception e) {
                logger.error("创建工作时发生错误：{}", convertJsonString(e.getMessage()));
            }
        }
    }

    /**
     * 执行工作
     */
    @Scheduled(fixedDelay = 2000)
    public void doWork() {
        String startWork = configMap.get(ConfigMapKeyEnum.START_WORK.getConfigKey());
        if (StringUtils.isEmpty(startWork) || !startWork.equals("1")) {
            return;
        }
        // 轮询工作站台，判断是否需要下发任务
        List<Stand> stands = standService.list(new LambdaQueryWrapper<Stand>()
                .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0)
                .eq(Stand::getStandType, 2));
        for (Stand workStation : stands) {
            try {
                // 执行工作
                workService.doWork(workStation.getStandId());
            } catch (Exception e) {
                logger.error("执行工作时发生错误：{}", convertJsonString(e.getMessage()));
            }
        }
    }

    /**
     * 每天查询一次是否有过期记录
     * 每天晚上10点执行一次
     */
    @Scheduled(cron = "0 0 22 * * ?")
    @Async("myThreadPool")
    public void deleteOutOfDateData() {
        // 删除日志数据
        wmsJobService.deleteLogsRegularly();
        // 删除记录数据
        wmsJobService.deleteRecordsRegularly();
    }
}