package cn.iocoder.yudao.module.system.mq.consumer.task;

import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.api.robot.vo.RobotWorkStatusDTO;
import cn.iocoder.yudao.module.system.constant.robot.RobotExecutionStateConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.RobotTaskTimeConsumingSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.log.RobotTaskTimeConsumingDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
import cn.iocoder.yudao.module.system.enums.robot.CommandTypeEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotTaskTypeEnum;
import cn.iocoder.yudao.module.system.enums.robot.task.WorkProgressEnum;
import cn.iocoder.yudao.module.system.enums.robot.task.event.EventTypeEnum;
import cn.iocoder.yudao.module.system.mq.message.task.TaskDistributionMessage;
import cn.iocoder.yudao.module.system.service.log.RobotTaskTimeConsumingService;
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService;
import cn.iocoder.yudao.module.system.service.robot.RobotTaskDetailService;
import cn.iocoder.yudao.module.system.service.robot.RobotTaskService;
import cn.iocoder.yudao.module.system.service.statistics.RobotWorkingHoursStatisticsService;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;


@Component
@Slf4j
public class TaskDistributionConsumer {

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private RobotTaskService taskService;

    @Resource
    private RobotTaskDetailService robotTaskDetailService;

    @Resource
    private RobotTaskTimeConsumingService robotTaskTimeConsumingService;

    @Resource
    private RobotWorkingHoursStatisticsService robotWorkingHoursStatisticsService;

    @Resource
    private PositionMapItemService positionMapItemService;

    @EventListener
    @Async
    public void onMessage(TaskDistributionMessage message) {
        log.info("111111, 任务 : {}", JSON.toJSONString(message));
        TenantContextHolder.setTenantId(1L);
        if (EventTypeEnum.TASK_DISTRIBUTION.getType().equals(message.getEventType())) {
            RobotTaskDetailDO taskDetail = robotTaskDetailService.getTaskDetail(Long.valueOf(message.getMessage()));
            robotWorkingHoursStatisticsService.createFreeTime(taskDetail.getRobotNo());
            RobotTaskDO task = taskService.getTask(taskDetail.getRobotTaskId());
            RobotTaskTimeConsumingSaveReqVO data = new RobotTaskTimeConsumingSaveReqVO()
                    .setTaskNo(task.getTaskNo())
                    .setTaskDetailId(taskDetail.getId())
                    .setFromLocationStorey(taskDetail.getFromLocationStorey())
                    .setFromLocationNo(taskDetail.getFromLocationNo())
                    .setToLocationStorey(taskDetail.getToLocationStorey())
                    .setToLocationNo(taskDetail.getToLocationNo())
                    .setRobotNo(taskDetail.getRobotNo());
            robotTaskTimeConsumingService.createRobotTaskTimeConsuming(data);
        } else if (EventTypeEnum.TASK_TIME.getType().equals(message.getEventType())) {
            RobotWorkStatusDTO data = JSON.parseObject(message.getMessage(), RobotWorkStatusDTO.class);
            addTaskTimeLog(data);
        } else if (EventTypeEnum.TASK_DONE.getType().equals(message.getEventType())) {
            String orderId = message.getMessage();
            String endTime = DateUtils.getYearMonthDayHourMinuteSecon();
            /*try {
                Thread.sleep(2000);
            } catch (Exception e) {
            }*/
            RobotTaskDetailDO taskDetail = robotTaskDetailService.getTaskDetail(Long.valueOf(orderId));
            if (RobotTaskTypeEnum.TAKE_RELEASE.getType().equals(taskDetail.getTaskType())) {
                takeRelease(taskDetail, endTime, orderId);
            } else if (RobotTaskTypeEnum.MOVE.getType().equals(taskDetail.getTaskType())) {
                moveTask(taskDetail, endTime, orderId);
            } else if (RobotTaskTypeEnum.TAKE.getType().equals(taskDetail.getTaskType())) {
                takeTask(taskDetail, endTime, orderId);
            } else if (RobotTaskTypeEnum.RELEASE.getType().equals(taskDetail.getTaskType())) {
                releaseTask(taskDetail, endTime, orderId);
            }else if (RobotTaskTypeEnum.MOVE_TO_POINT.getType().equals(taskDetail.getTaskType())) {
                positionMapItemService.setMapItemUse(taskDetail.getReleaseId(),taskDetail.getRobotNo());
            }

        }
    }

    private void releaseTask(RobotTaskDetailDO taskDetail, String endTime, String orderId) {
        Duration duration = Duration.between(taskDetail.getStartTime(), taskDetail.getEndTime());
        //总时间
        Long totalTimeConsuming = duration.getSeconds();

        String startDropKey = RobotTaskChcheConstant.ROBOT_TASK_START_DROP + orderId;
        Object startDropObj = redisUtil.get(startDropKey);

        Long dropTimeConsuming = getSeconds(startDropObj, endTime);

        RobotTaskTimeConsumingDO data = new RobotTaskTimeConsumingDO()
                .setTaskDetailId(Long.valueOf(orderId))
                .setTotalTimeConsuming(totalTimeConsuming + "")
                .setDropTimeConsuming(dropTimeConsuming + "");
        robotTaskTimeConsumingService.updateConsuming(data);
    }

    private void takeTask(RobotTaskDetailDO taskDetail, String endTime, String orderId) {
        Duration duration = Duration.between(taskDetail.getStartTime(), taskDetail.getEndTime());
        //总时间
        Long totalTimeConsuming = duration.getSeconds();

        String startPickKey = RobotTaskChcheConstant.ROBOT_TASK_START_PICK + orderId;
        Object startPickObj = redisUtil.get(startPickKey);

        String endPickKey = RobotTaskChcheConstant.ROBOT_TASK_END_PICK + orderId;
        Object endPickObj = redisUtil.get(endPickKey);

        Long pickTimeConsuming = getSeconds(startPickObj, endPickObj);

        RobotTaskTimeConsumingDO data = new RobotTaskTimeConsumingDO()
                .setTaskDetailId(Long.valueOf(orderId))
                .setTotalTimeConsuming(totalTimeConsuming + "")
                .setPickTimeConsuming(pickTimeConsuming + "");
        robotTaskTimeConsumingService.updateConsuming(data);
    }

    private void moveTask(RobotTaskDetailDO taskDetail, String endTime, String orderId) {
        Duration duration = Duration.between(taskDetail.getStartTime(), taskDetail.getEndTime());
        //总时间
        Long totalTimeConsuming = duration.getSeconds();
        RobotTaskTimeConsumingDO data = new RobotTaskTimeConsumingDO()
                .setTaskDetailId(Long.valueOf(orderId))
                .setTotalTimeConsuming(totalTimeConsuming + "");
        robotTaskTimeConsumingService.updateConsuming(data);
    }

    private void takeRelease(RobotTaskDetailDO taskDetail, String endTime, String orderId) {
        Duration duration = Duration.between(taskDetail.getStartTime(), taskDetail.getEndTime());
        //总时间
        Long totalTimeConsuming = duration.getSeconds();

        String startPickKey = RobotTaskChcheConstant.ROBOT_TASK_START_PICK + orderId;
        Object startPickObj = redisUtil.get(startPickKey);

        String endPickKey = RobotTaskChcheConstant.ROBOT_TASK_END_PICK + orderId;
        Object endPickObj = redisUtil.get(endPickKey);

        Long pickTimeConsuming = getSeconds(startPickObj, endPickObj);

        String startDropKey = RobotTaskChcheConstant.ROBOT_TASK_START_DROP + orderId;
        Object startDropObj = redisUtil.get(startDropKey);

        Long dropTimeConsuming = getSeconds(startDropObj, taskDetail.getEndTime());
        Long checkTimeConsuming = getSeconds(startPickObj, taskDetail.getEndTime());

        RobotTaskTimeConsumingDO data = new RobotTaskTimeConsumingDO()
                .setTaskDetailId(Long.valueOf(orderId))
                .setTotalTimeConsuming(totalTimeConsuming + "")
                .setPickTimeConsuming(pickTimeConsuming + "")
                .setDropTimeConsuming(dropTimeConsuming + "")
                .setCheckTimeConsuming(checkTimeConsuming + "");
        robotTaskTimeConsumingService.updateConsuming(data);
    }

    public Long getSeconds(Object startObj, Object endObj) {
        String startObjStr = startObj.toString().replaceAll("T"," ");
        String endObjStr = endObj.toString().replaceAll("T"," ");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime startTime = LocalDateTime.parse(startObjStr, formatter);
        LocalDateTime endTime = LocalDateTime.parse(endObjStr, formatter);
        Duration duration = Duration.between(startTime, endTime);
        log.info("开始时间 :{}, 结束时间 :{}, 间隔 :{}",startObj,endObj,duration.getSeconds());
        return duration.getSeconds();
    }


    /**
     * 统计工作时间
     *
     * @param data
     */
    private void addTaskTimeLog(RobotWorkStatusDTO data) {
        if (CommandTypeEnum.WORK_PICK_UP_GOODS.getType().equals(data.getCommandType())
                && WorkProgressEnum.FORK_AND_TILT.getType().equals(data.getWorkProgress())
                && RobotExecutionStateConstant.DOING.equals(Integer.valueOf(data.getExecutionState()))) {
            startPickUp(data);
        } else if (CommandTypeEnum.WORK_PICK_UP_GOODS.getType().equals(data.getCommandType())
                && WorkProgressEnum.FORK_AND_TILT_INIT.getType().equals(data.getWorkProgress())
                && RobotExecutionStateConstant.DONE.equals(Integer.valueOf(data.getExecutionState()))) {
            endPickUp(data);
        } else if (CommandTypeEnum.WORK_DROP_OFF_GOODS_MOVE_TO_CHECK.getType().equals(data.getCommandType())
                && RobotExecutionStateConstant.DONE.equals(Integer.valueOf(data.getExecutionState()))) {
            startDrop(data);
        }
    }

    private void startDrop(RobotWorkStatusDTO data) {
        String key = RobotTaskChcheConstant.ROBOT_TASK_START_DROP + data.getOrderId();
        String yearMonthDayHourMinuteSecon = DateUtils.getYearMonthDayHourMinuteSecon();
        redisUtil.set(key, yearMonthDayHourMinuteSecon, 86400);
        log.info("111111任务:{}, 开始放货:{}", data.getOrderId(), yearMonthDayHourMinuteSecon);
    }

    private void endPickUp(RobotWorkStatusDTO data) {
        String key = RobotTaskChcheConstant.ROBOT_TASK_END_PICK + data.getOrderId();
        String yearMonthDayHourMinuteSecon = DateUtils.getYearMonthDayHourMinuteSecon();
        redisUtil.set(key, yearMonthDayHourMinuteSecon, 86400);
        log.info("111111任务:{}, 取货完成:{}", data.getOrderId(), yearMonthDayHourMinuteSecon);
    }

    private void startPickUp(RobotWorkStatusDTO data) {
        String key = RobotTaskChcheConstant.ROBOT_TASK_START_PICK + data.getOrderId();
        String yearMonthDayHourMinuteSecon = DateUtils.getYearMonthDayHourMinuteSecon();
        redisUtil.set(key, yearMonthDayHourMinuteSecon, 86400);
        log.info("111111任务:{}, 开始取货:{}", data.getOrderId(), yearMonthDayHourMinuteSecon);
    }


}
