package com.shkj.wcs.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shkj.common.core.domain.Result;
import com.shkj.common.utils.DateUtils;
import com.shkj.wcs.bo.AGVFeedbackBo;
import com.shkj.wcs.bo.ExtraData;
import com.shkj.wcs.bo.WcsPlcPropertyQueryBo;
import com.shkj.wcs.domain.BusinDataTask;
import com.shkj.wcs.domain.WcsPlcProperty;
import com.shkj.wcs.mapper.BusinDataTaskMapper;
import com.shkj.wcs.mapper.WcsPlcPropertyMapper;
import com.shkj.wcs.plc.PlcEventTask;
import com.shkj.wcs.service.IBusinDataTaskService;
import com.shkj.wcs.service.IWcsPlcPropertyService;
import com.shkj.wcs.third.rcs.CounterService;
import com.shkj.wcs.third.rcs.RCSUtil;
import com.shkj.wcs.third.rcs.dto.CarrierInfoList;
import com.shkj.wcs.third.rcs.dto.RcsCancelTaskDto;
import com.shkj.wcs.third.rcs.dto.RcsCreateTaskDto;
import com.shkj.wcs.third.rcs.dto.RcsIdList;
import com.shkj.wcs.third.rcs.enums.RCSOperation;
import com.shkj.wcs.third.rcs.enums.RCSTaskTypeEnum;
import com.shkj.wcs.third.rcs.vo.RcsResponseVo;
import com.shkj.wcs.third.workbinWcs.WCSUtil;
import com.shkj.wcs.third.workbinWcs.dto.*;
import com.shkj.wcs.vo.WcsResponseVo;
import com.shkj.wms.enums.MapEnum;
import com.shkj.wms.enums.TaskStatusEnum;
import com.shkj.wms.enums.TaskTypeEnum;
import com.shkj.wms.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * PLC连接属性Service业务层处理
 *
 * @author zjx
 * @date 2023-04-21
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class BusinDataTaskServiceImpl extends ServiceImpl<BusinDataTaskMapper, BusinDataTask> implements IBusinDataTaskService {


    @Autowired
    private IBusinDataTaskService iBusinDataTaskService;
    @Autowired
    private WCSUtil wcsUtil;
    @Autowired
    private RCSUtil rcsUtil;

    @Autowired
    private PlcEventTask plcEventTask;

    @Override
    public WcsResponseVo doTaskGeneratePickTask(WcsCreateTaskDto bo) {
        if (bo != null) {
            log.info("中科下发任务请求数据:" + JSONObject.toJSONString(bo));
            List<WcsCreateTaskBody> body = bo.getBody();
            if (!body.isEmpty()) {
                for (WcsCreateTaskBody by : body) {
                    String taskId = by.getTaskId();
                    String trayCode = by.getTrayCode();
                    String taskType = by.getTaskType();
                    String fromBinCode = by.getFromBinCode();
                    String toBinCode = by.getToBinCode();
                    String agvType = by.getAgvType();
                    String dataChange = by.getDataChange();
                    String priority = by.getPriority();
                    LambdaQueryWrapper<BusinDataTask> lqwDataTask = new LambdaQueryWrapper<BusinDataTask>()
                            .eq(BusinDataTask::getContainerCode, trayCode)
                            .in(BusinDataTask::getTaskStatus, TaskStatusEnum.wait_put.getValue(), TaskStatusEnum.wait_callback.getValue());
                    BusinDataTask one = this.getOne(lqwDataTask);
                    if (dataChange.equals("1")) {
                        if (one != null) {
                            log.info("该托盘" + trayCode + "存在未完成的任务");
                            return WcsResponseVo.error(500, "该托盘" + trayCode + "存在未完成的任务");
                        }
                        BusinDataTask businDataTask = new BusinDataTask();
                        businDataTask.setTaskCode(taskId);
                        businDataTask.setTaskType(taskType);
                        businDataTask.setAgvType(agvType);
                        businDataTask.setContainerCode(trayCode);
                        businDataTask.setFromSide(fromBinCode);
                        businDataTask.setToSide(toBinCode);
                        businDataTask.setTaskPath(toBinCode);
                        businDataTask.setTaskStatus(TaskStatusEnum.wait_put.getValue());
                        businDataTask.setCreateTime(DateUtils.getNowDate());
                        if (!priority.isEmpty()) {
                            businDataTask.setPriority(priority);
                        }
                        boolean save = this.save(businDataTask);
                        if (save) {
                            //调用下游接口下任务
                            log.info("任务储存成功！");
                            Result result = rcsTaskIssued(businDataTask);
                            if (!Result.isOk(result)) {
                                return WcsResponseVo.error(200, "接受成功但给rcs下发任务失败");
                            }
                            businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                            businDataTask.setTaskStarttime(DateUtils.getNowDate());
                            iBusinDataTaskService.updateById(businDataTask);
                            if (fromBinCode.equals("SC-G2-00-00-2003")) {
                                Boolean aBoolean = plcEventTask.plcExecWrite(2);
                                if (!aBoolean) {
                                    return WcsResponseVo.error(200, "接受成功但给plc回传任务失败");
                                }
                            }

                        }
                        return WcsResponseVo.error(500, "任务存储失败");
                        //任务取消
                    } else if (dataChange.equals("2")) {
                        if (one == null) {
                            return WcsResponseVo.error(500, "未查询到该托盘" + trayCode + "存在未完成的任务");
                        }

                        //推送给下游
                        RcsCancelTaskDto rcsCancelTaskDto = new RcsCancelTaskDto();
                        rcsCancelTaskDto.setRobotTaskCode(taskId);
//                        if (one.getTaskStatus().equals(TaskStatusEnum.wait_put.getValue())) {
//                            //软取消
//                            rcsCancelTaskDto.setCancelType("CANCEL");
//                        } else {
                            //硬取消（人工介入）
                            rcsCancelTaskDto.setCancelType("DROP");

//                        }
                        Result result = rcsUtil.rcsTaskCancel(rcsCancelTaskDto);
                        if (!Result.isOk(result)) {
                            return WcsResponseVo.error(500, "给rcs取消任务失败");
                        }
                        one.setTaskStatus("3");
                        this.updateById(one);
                    }
                    return WcsResponseVo.success();
                }
            }
        } else {
            log.info("中科下发任务请求数据为空");
        }
        return WcsResponseVo.error(500, "请求失败请检查参数");
    }

    @Override
    public RcsResponseVo rcsFeedbackTask(AGVFeedbackBo bo) {
        log.info("agv任务执行过程回馈数据:" + JSONObject.toJSONString(bo));
        String robotTaskCode = bo.getRobotTaskCode();
        ExtraData.Values values = bo.getExtra().getValues();
        String carrierCode = values.getCarrierCode();
        String method = values.getMethod();
        String slotName = values.getSlotName();
        LambdaQueryWrapper<BusinDataTask> queryWrapper = new LambdaQueryWrapper<BusinDataTask>()
                .eq(BusinDataTask::getTaskCode, robotTaskCode);
//                .eq(BusinDataTask::getContainerCode, carrierCode);
        BusinDataTask businDataTask;
        try {
            businDataTask = iBusinDataTaskService.getOne(queryWrapper, true);
        } catch (TooManyResultsException e) {
            log.error("任务编号 {} 存在重复记录", robotTaskCode);
            return RcsResponseVo.error("任务编号存在重复记录");
        }

        if (businDataTask == null) {
            log.warn("未找到对应任务，任务号：{}", robotTaskCode);
            return RcsResponseVo.error("未找到对应任务");
        }
        businDataTask.setAgvTaskStatus(method);
        businDataTask.setUpdateTime(new Date());
        businDataTask.setAgvNo(bo.getSingleRobotCode());
        boolean isUpdated = iBusinDataTaskService.updateById(businDataTask);
        if (!isUpdated) {
            log.error("任务状态更新失败，任务号：{}", robotTaskCode);
            return RcsResponseVo.error("任务状态更新失败");
        }
        log.info("agv任务状态更新成功，任务号：{}", robotTaskCode);
        if(!businDataTask.getTaskType().equals(TaskTypeEnum.Out.getValue())){
        switch (method) {
            case "start":
                businDataTask.setTaskStarttime(new Date());
                businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                break;
            case "outbin":
                businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                break;
            case "end":
                businDataTask.setTaskStatus(TaskStatusEnum.finished.getValue());
                businDataTask.setDestination(slotName);
                businDataTask.setTaskEntime(new Date());
                break;
            case "cancel":
                businDataTask.setTaskStatus(TaskStatusEnum.clean.getValue());
                businDataTask.setDestination(slotName);
                break;
            default:
                return RcsResponseVo.error("任务状态未知！");
        }
            boolean bool = iBusinDataTaskService.updateById(businDataTask);
            if (!bool) {
                log.error("总任务状态更新失败，任务号：{}", robotTaskCode);
                return RcsResponseVo.error("总任务状态更新失败");
            }
            log.info("总任务状态更新成功，任务号：{}", robotTaskCode);
            UploadWCSTaskStatusDto uploadWCSTaskStatusDto = new UploadWCSTaskStatusDto();
            WcsCreateTaskHeader header = new WcsCreateTaskHeader();
            String taskType = businDataTask.getTaskType();
            switch (taskType) {
                case "1":
                    header.setBusinessType("stockOutReturn");
                    break;
                case "2":
                    header.setBusinessType("stockInReturn");
                    break;
                case "3":
                    header.setBusinessType("transferReturn");
                    break;
                default:
                    return RcsResponseVo.error("未知任务类型！");
            }
            uploadWCSTaskStatusDto.setHeader(header);
            UploadWCSTaskStatusBody body = new UploadWCSTaskStatusBody();
            List<UploadWCSTaskStatusBody> bodyList = new ArrayList<>();
            body.setTaskId(businDataTask.getTaskCode());
            body.setTrayCode(carrierCode);
            body.setTaskType(taskType);
            body.setStatus(businDataTask.getTaskStatus());
//        if (businDataTask.getTaskStatus().equals(TaskStatusEnum.finished.getValue())) {
            if(slotName.equals("0187000XY0234215")){
                slotName = "SC-G2-00-00-43022";
            }
            body.setDestination(slotName);
//        }
            body.setMsgCode("200");
            bodyList.add(body);
            uploadWCSTaskStatusDto.setBody(bodyList);
            log.info("请求zk-wcs参数{}", JSONObject.toJSONString(uploadWCSTaskStatusDto));
            try {
                WcsResponseVo vo = wcsUtil.uploadWCSTaskStatus(uploadWCSTaskStatusDto);
                log.info("WZ-WCS状态上报反馈："+ JSONObject.toJSONString(vo));
            } catch (TooManyResultsException e) {
                log.error("WZ-WCS状态上报异常，任务号：{}", robotTaskCode, e);
                return RcsResponseVo.error("KJ-WCS状态上报异常");
            }
        }


        return RcsResponseVo.success(new JSONObject().fluentPut("data", robotTaskCode));
    }

    @Override
    public Result rcsTaskIssued(BusinDataTask businDataTask) {
        String toSide = businDataTask.getToSide();
        RcsCreateTaskDto rcsCreateTaskDto = new RcsCreateTaskDto();
        rcsCreateTaskDto.setTaskType(businDataTask.getAgvType());
        rcsCreateTaskDto.setRobotTaskCode(businDataTask.getTaskCode());
        if (!businDataTask.getPriority().isEmpty()) {
            rcsCreateTaskDto.setInitPriority(Integer.parseInt(businDataTask.getPriority()));
        }
        List<RcsIdList> rcsIdLists = new ArrayList<>();
        for (int i = 1; i <= 2; i++) {
            RcsIdList rcsIdList = new RcsIdList();

            rcsIdList.setType("SITE");
            if (i == 1) {
                rcsIdList.setSeq(0);
                rcsIdList.setCode(businDataTask.getFromSide());
                rcsIdList.setOperation(RCSOperation.OT_COLLECT.getValue());
            } else {
                rcsIdList.setSeq(1);
                if(toSide.equals(MapEnum.oneOut.getValue())){
                    toSide = MapEnum.twoDownIn.getValue();
                }
                rcsIdList.setCode(toSide);
                rcsIdList.setOperation(RCSOperation.OT_DELIVERY.getValue());
            }
            rcsIdList.setAutoStart(1);
            rcsIdLists.add(rcsIdList);
        }
        rcsCreateTaskDto.setTargetRoute(rcsIdLists);
        CarrierInfoList carrierInfoList = new CarrierInfoList();
        String substring = toSide.substring(4, 5);
        int number = Integer.parseInt(substring);
        int carrierCode = 0;
        if(number ==2){
            carrierCode = CounterService.incrementAndGet(2);
        }

        carrierInfoList.setCarrierCode(String.valueOf(carrierCode));
        carrierInfoList.setCarrierType("4");
        carrierInfoList.setLayer("0");
        List<CarrierInfoList> carrierInfoLists = new ArrayList<>();
        carrierInfoLists.add(carrierInfoList);
        Map<String, Object> extra = new HashMap<>();
        extra.put("carrierInfo", carrierInfoLists);
        rcsCreateTaskDto.setExtra(extra);
        return  rcsUtil.rcsCreateTask(rcsCreateTaskDto);
    }


}
