package com.wcs.back.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wcs.back.domain.*;
import com.wcs.back.service.IWcsService;
import com.wcs.back.util.http.HttpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * wcs回调Service
 *
 * @author zf
 * @date 2023/11/27
 */
@Service
public class WcsServiceImpl implements IWcsService {
    private static final Logger log = LoggerFactory.getLogger(WcsServiceImpl.class);

    @Value("${wms.httpUrl}")
    public String httpUrl;

    @Value("${wms.roboticArmUrl}")
    public String roboticArmUrl;

    @Value("${wms.ctuUrl}")
    public String ctuUrl;

    @Value("${wms.drumLineTaskHttpUrl}")
    public String drumLineTaskHttpUrl;

    /**
     * 普通搬运任务下发
     *
     * @param json
     * @return
     */
    @Override
    public WcsResult SetUp_Task(String json, HttpServletRequest request) throws JsonProcessingException {
        // 获取客户端IP地址
        String clientIpAddress = getClientIpAddress(request);
        String url = "http://"+clientIpAddress+httpUrl;

        // 创建一个 ScheduledExecutorService 实例
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

        ObjectMapper objectMapper = new ObjectMapper();
        List<AgvSetUpTask> agvSetUpTaskList = objectMapper.readValue(json, objectMapper.getTypeFactory().constructCollectionType(List.class, AgvSetUpTask.class));
        // 创建两个倒计时任务
        // 1.30秒后回调取料成功
        AgvSetUpTask agvSetUpTask = agvSetUpTaskList.get(0);
        // 2.60秒后回调已送达
        AgvSetUpTask agvSetUpTask2 = agvSetUpTaskList.get(1);
        // 定义第一个任务,30秒后执行
        Runnable task1 = () -> {
            // 回调1的具体逻辑
            TaskCallBack taskCallBack = new TaskCallBack();
            taskCallBack.setTaskNo(agvSetUpTask.getTaskNo());
            taskCallBack.setTaskIndex(agvSetUpTask.getTaskIndex());
            taskCallBack.setArmSite(agvSetUpTask.getArmSite());
            taskCallBack.setActionType(agvSetUpTask.getActionType());
            taskCallBack.setAgv(1);
            taskCallBack.setTaskState(2);
            taskCallBack.setExeAgv(1);
            sendHttpPost(taskCallBack, url);
        };

        // 定义第二个任务,60秒后执行
        Runnable task2 = () -> {
            // 任务2的具体逻辑
            TaskCallBack taskCallBack2 = new TaskCallBack();
            taskCallBack2.setTaskNo(agvSetUpTask2.getTaskNo());
            taskCallBack2.setTaskIndex(agvSetUpTask2.getTaskIndex());
            taskCallBack2.setArmSite(agvSetUpTask2.getArmSite());
            taskCallBack2.setActionType(agvSetUpTask2.getActionType());
            taskCallBack2.setAgv(1);
            taskCallBack2.setTaskState(3);
            taskCallBack2.setExeAgv(1);
            sendHttpPost(taskCallBack2, url);
        };
        // 安排任务1,30秒后执行
        scheduler.schedule(task1, 30, TimeUnit.SECONDS);

        // 安排任务2,60秒后执行
        scheduler.schedule(task2, 60, TimeUnit.SECONDS);

        WcsResult wcsResult = new WcsResult();
        wcsResult.setResultCode(1);
        wcsResult.setMessage("成功");
        return wcsResult;
    }

    /**
     * 机械臂拆托任务下发
     *
     * @param json
     * @param request
     * @return
     */
    @Override
    public WcsResult Dismantling_Task(String json, HttpServletRequest request) throws JsonProcessingException {
        // 获取客户端IP地址
        String clientIpAddress = getClientIpAddress(request);
        String url = "http://"+clientIpAddress+roboticArmUrl;
        // 滚筒url,已送达是滚筒返回
        String gtUrl = "http://"+clientIpAddress+drumLineTaskHttpUrl;
        ObjectMapper objectMapper = new ObjectMapper();
        RoboticArmTaskVo roboticArmTaskVo = objectMapper.readValue(json, RoboticArmTaskVo.class);
        List<RoboticArmTaskVo.DismantlingInfo> armSiteList = roboticArmTaskVo.getArmSiteList();
        int size = armSiteList.size();
        // 创建一个 ScheduledExecutorService 实例
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2+(2*size));

        // 创建倒计时任务
        // 1.30秒后回调取料成功
        // 2.60秒后,每隔10秒回调拆箱成功,如果全部拆箱完成,则过10秒回调拆托完成
        // 3.等2的任务全部做完后,等待10秒,每隔10秒回调已送达(目的区域是20-分拣区)

        // 取料成功
        Runnable task1 = () -> {
            // 回调1的具体逻辑
            RoboticArmTaskBackVo roboticArmTaskBackVo = new RoboticArmTaskBackVo();
            roboticArmTaskBackVo.setTaskNo(roboticArmTaskVo.getTaskNo());
            roboticArmTaskBackVo.setTaskState("10");
            roboticArmTaskBackVo.setRemark("取料成功!");
            sendHttpPost(roboticArmTaskBackVo, url);
        };
        // 30秒之后执行,取料成功
        scheduler.schedule(task1, 30, TimeUnit.SECONDS);
        // 拆箱成功
        Integer time = 60;
        for (RoboticArmTaskVo.DismantlingInfo dismantlingInfo : armSiteList){
            Runnable taskSite = () -> {
                // 回调1的具体逻辑
                RoboticArmTaskBackVo roboticArmTaskBackVo = new RoboticArmTaskBackVo();
                roboticArmTaskBackVo.setTaskNo(roboticArmTaskVo.getTaskNo());
                roboticArmTaskBackVo.setDisassemblyTaskNo(dismantlingInfo.getDisassemblyTaskNo());
                // 料箱号只能模拟从wms调用空料箱
                String materialBinId = HttpUtils.HttpPostWithJson("http://"+clientIpAddress+":50902/wcs/getEmptyPallet", "");
                dismantlingInfo.setMaterialBinId(materialBinId);
                roboticArmTaskBackVo.setMaterialBinId(materialBinId);
                roboticArmTaskBackVo.setTaskState("20");
                roboticArmTaskBackVo.setRemark("拆箱成功!");
                sendHttpPost(roboticArmTaskBackVo, url);
            };
            // 循环执行拆箱回调
            scheduler.schedule(taskSite, time, TimeUnit.SECONDS);
            time += 10;
        }

        // 拆托成功,在全部拆箱完成之后执行
        Runnable ctTask = () -> {
            // 回调1的具体逻辑
            RoboticArmTaskBackVo roboticArmTaskBackVo = new RoboticArmTaskBackVo();
            roboticArmTaskBackVo.setTaskNo(roboticArmTaskVo.getTaskNo());
            roboticArmTaskBackVo.setTaskState("30");
            roboticArmTaskBackVo.setRemark("拆托成功!");
            sendHttpPost(roboticArmTaskBackVo, url);
        };
        scheduler.schedule(ctTask, time, TimeUnit.SECONDS);

        // 送至分拣需要回调已送达
        time += 10;
        for (RoboticArmTaskVo.DismantlingInfo dismantlingInfo : armSiteList){
            if (dismantlingInfo.getDestinationArea().equals("20")){
                Runnable taskSite = () -> {
                    RoboticArmTaskBackVo roboticArmTaskBackVo = new RoboticArmTaskBackVo();
                    roboticArmTaskBackVo.setTaskNo(roboticArmTaskVo.getTaskNo());
                    roboticArmTaskBackVo.setDisassemblyTaskNo(dismantlingInfo.getDisassemblyTaskNo());
                    roboticArmTaskBackVo.setMaterialBinId(dismantlingInfo.getMaterialBinId());
                    roboticArmTaskBackVo.setTaskState("40");
                    roboticArmTaskBackVo.setRemark("已送达!");
                    sendHttpPost(roboticArmTaskBackVo, gtUrl);
                };
                // 循环执行拆箱回调
                scheduler.schedule(taskSite, time, TimeUnit.SECONDS);
                time += 10;
            }
        }

        WcsResult wcsResult = new WcsResult();
        wcsResult.setResultCode(1);
        wcsResult.setMessage("成功");
        return wcsResult;
    }

    /**
     * CTU任务下发
     *
     * @param json
     * @param request
     * @return
     */
    @Override
    public WcsResult SetUp_CTUTask(String json, HttpServletRequest request) throws JsonProcessingException {
        // 获取客户端IP地址
        String clientIpAddress = getClientIpAddress(request);
        String url = "http://"+clientIpAddress+ctuUrl;
        ObjectMapper objectMapper = new ObjectMapper();
        CTUTaskVo ctuTaskVo = objectMapper.readValue(json, CTUTaskVo.class);
        List<CTUTaskVo.Site> siteList = ctuTaskVo.getSiteList();
        int size = siteList.size();

        // 创建一个 ScheduledExecutorService 实例
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2*size);

        // 创建倒计时任务
        // 循环取料成功
        Integer time = 10;
        for (CTUTaskVo.Site site : siteList){
            Runnable taskSite = () -> {
                CTUTaskBackVo ctuTaskBackVo = new CTUTaskBackVo();
                ctuTaskBackVo.setTaskNo(ctuTaskVo.getTaskNo());
                ctuTaskBackVo.setMaterialBinId(site.getMaterialBinId());
                ctuTaskBackVo.setBizNo(site.getBizNo());
                ctuTaskBackVo.setTaskState("10");
                ctuTaskBackVo.setRemark("取料成功!");
                sendHttpPost(ctuTaskBackVo, url);
            };
            // 循环执行取料成功回调
            scheduler.schedule(taskSite, time, TimeUnit.SECONDS);
            time += 10;
        }

        // 循环已送达
        time += 20;
        for (CTUTaskVo.Site site : siteList){
            Runnable taskSite = () -> {
                CTUTaskBackVo ctuTaskBackVo = new CTUTaskBackVo();
                ctuTaskBackVo.setTaskNo(ctuTaskVo.getTaskNo());
                ctuTaskBackVo.setMaterialBinId(site.getMaterialBinId());
                ctuTaskBackVo.setBizNo(site.getBizNo());
                ctuTaskBackVo.setTaskState("40");
                ctuTaskBackVo.setRemark("已送达!");
                sendHttpPost(ctuTaskBackVo, url);
            };
            // 循环执行送达回调
            scheduler.schedule(taskSite, time, TimeUnit.SECONDS);
            time += 10;
        }
        WcsResult wcsResult = new WcsResult();
        wcsResult.setResultCode(1);
        wcsResult.setMessage("成功");
        return wcsResult;
    }

    /**
     * 滚筒线任务下发
     *
     * @param json
     * @param request
     * @return
     */
    @Override
    public WcsResult DrumLine_Task(String json, HttpServletRequest request) throws JsonProcessingException {
        // 获取客户端IP地址
        String clientIpAddress = getClientIpAddress(request);
        String url = "http://"+clientIpAddress+drumLineTaskHttpUrl;
        ObjectMapper objectMapper = new ObjectMapper();
        DrumLineTaskVo drumLineTaskVo = objectMapper.readValue(json, DrumLineTaskVo.class);

        // 创建一个 ScheduledExecutorService 实例
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        // 创建倒计时任务
        Runnable task = () -> {
            DrumLineTaskBackVo drumLineTaskBackVo = new DrumLineTaskBackVo();
            drumLineTaskBackVo.setTaskNo(drumLineTaskVo.getTaskNo());
            drumLineTaskBackVo.setTaskState("40");
            drumLineTaskBackVo.setMaterialBinId(drumLineTaskVo.getBusinessNo());
            drumLineTaskBackVo.setRemark("已送达!");
            sendHttpPost(drumLineTaskBackVo, url);
        };
        // 30秒后执行已送达回调
        scheduler.schedule(task, 30, TimeUnit.SECONDS);

        WcsResult wcsResult = new WcsResult();
        wcsResult.setResultCode(1);
        wcsResult.setMessage("成功");
        return wcsResult;
    }

    /**
     * 指令下发
     *
     * @param json
     * @param request
     * @return
     */
    @Override
    public WcsResult Directives(String json, HttpServletRequest request) throws JsonProcessingException {
        // 获取客户端IP地址
        String clientIpAddress = getClientIpAddress(request);

        // 创建一个 ScheduledExecutorService 实例
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        ObjectMapper objectMapper = new ObjectMapper();
        DirectivesVo directivesVo = objectMapper.readValue(json, DirectivesVo.class);

        WcsResult wcsResult = new WcsResult();
        wcsResult.setResultCode(1);
        wcsResult.setMessage("成功");
        return wcsResult;
    }

    // 发送 HTTP POST 请求
    private <T> WcsResult sendHttpPost(T taskCallBack, String url) {
        String jsonString = JSON.toJSONString(taskCallBack);
        String sendPost = HttpUtils.HttpPostWithJson(url, jsonString);
        WcsResult agvResult = JSONObject.parseObject(sendPost, WcsResult.class);
        // 处理回调结果,根据具体逻辑设置
        log.info("请求json:"+jsonString);
        log.info("响应json:"+agvResult.toString());
        return agvResult;
    }

    // 获取请求端ip地址
    private String getClientIpAddress(HttpServletRequest request) {
        String xForwardedForHeader = request.getHeader("X-Forwarded-For");
        if (xForwardedForHeader == null) {
            return request.getRemoteAddr();
        }
        // 如果使用了代理服务器,X-Forwarded-For头部可以包含多个IP地址,从左到右是从原始客户端到最近的代理服务器
        // 这里简单地取第一个IP地址作为客户端IP地址
        return xForwardedForHeader.split(",")[0].trim();
    }
}