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.service.IBusinDataTaskService;
import com.shkj.wcs.service.IWcsPlcPropertyService;
import com.shkj.wcs.third.rcs.RCSUtil;
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.TaskStatusEnum;
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.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 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;

    @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 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) {
                            return WcsResponseVo.error(500, "该托盘" + trayCode + "存在未完成的任务");
                        }
                        BusinDataTask businDataTask = new BusinDataTask();
                        businDataTask.setTaskCode(taskId);
                        businDataTask.setTaskType(taskType);
                        businDataTask.setContainerCode(trayCode);
                        businDataTask.setFromSide(fromBinCode);
                        businDataTask.setToSide(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("任务储存成功！");
                            RcsCreateTaskDto rcsCreateTaskDto = new RcsCreateTaskDto();
                            rcsCreateTaskDto.setTaskType(RCSTaskTypeEnum.PF_LMR_COMMON.getValue());
                            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();
                                if (i == 1) {
                                    rcsIdList.setType("ZONE");
                                    rcsIdList.setCode(businDataTask.getFromSide());
                                    rcsIdList.setOperation(RCSOperation.OT_COLLECT.getValue());
                                }
                                rcsIdList.setType("ZONE");
                                rcsIdList.setCode(businDataTask.getToSide());
                                rcsIdList.setOperation(RCSOperation.OT_DELIVERY.getValue());
                                rcsIdLists.add(rcsIdList);
                            }
                            rcsCreateTaskDto.setTargetRoute(rcsIdLists);

                            Result result = rcsUtil.rcsCreateTask(rcsCreateTaskDto);
                            if (!Result.isOk(result)){
                                return WcsResponseVo.error(200,"给rcs下发任务失败");
                            }
                        }
                        //任务取消
                    } else if (dataChange.equals("2")) {
                        if (one == null) {
                            return WcsResponseVo.error(500, "未查询到该托盘" + trayCode + "存在未完成的任务");
                        }
                        one.setTaskStatus("6");
                        this.updateById(one);
                        //推送给下游
                        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(200,"给rcs取消任务失败");
                        }
                    }
                    return WcsResponseVo.success();
                }
            }
        }else{
            log.info("中科下发任务请求数据为空");
        }
        return WcsResponseVo.error(500,"请求失败请检查参数");
    }

    @Override
    public RcsResponseVo rcsFeedbackTask(AGVFeedbackBo 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("未找到对应任务");
        }

        String taskType = businDataTask.getTaskType();
        switch (method) {
            case "start":
            case "outbin":
                businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
                break;
            case "end":
                businDataTask.setTaskStatus(TaskStatusEnum.finished.getValue());
                businDataTask.setDestination(slotName);
                break;
            default:
                return  RcsResponseVo.error("任务状态未知！");
        }
        businDataTask.setUpdateTime(new Date());
        boolean isUpdated  = iBusinDataTaskService.updateById(businDataTask);
        if (!isUpdated) {
            log.error("任务状态更新失败，任务号：{}", robotTaskCode);
            return RcsResponseVo.error("任务状态更新失败");
        }
        log.info("任务状态更新成功，任务号：{}", robotTaskCode);
        UploadWCSTaskStatusDto uploadWCSTaskStatusDto = new UploadWCSTaskStatusDto();
        WcsCreateTaskHeader header = new WcsCreateTaskHeader();
        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())){
            body.setDestination(slotName);
        }
        body.setMsgCode("200");
        bodyList.add(body);
        uploadWCSTaskStatusDto.setBody(bodyList);
        log.info("请求zk-wcs参数{}",JSONObject.toJSONString(uploadWCSTaskStatusDto));
        try {
            wcsUtil.uploadWCSTaskStatus(uploadWCSTaskStatusDto);
        } catch (TooManyResultsException e) {
            log.error("WZ-WCS状态上报异常，任务号：{}", robotTaskCode, e);
            return RcsResponseVo.error("KJ-WCS状态上报异常");
        }
        return RcsResponseVo.success(new JSONObject().fluentPut("data", robotTaskCode));
    }


}
