package com.shkj.wcs.third.rcs;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.shkj.common.constant.RedisConstant;
import com.shkj.common.core.domain.Result;
import com.shkj.plc.sdk.device.PLCReadAndWrite;
import com.shkj.plc.sdk.device.PlcOperate;
import com.shkj.system.service.ISysParameterService;
import com.shkj.wcs.bo.AGVStatesBo;
import com.shkj.wcs.bo.AGVUploadStatusBo;
import com.shkj.wcs.domain.WcsPlcConnect;
import com.shkj.wcs.domain.WcsPlcProperty;
import com.shkj.wcs.plc.PlcInit;
import com.shkj.wcs.service.IWcsPlcConnectService;
import com.shkj.wcs.service.IWcsPlcPropertyService;
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.dto.RcsThirdResult;
import com.shkj.wms.bo.AGVMoveBo;
import com.shkj.wcs.mapper.BusinDataTaskMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

/**
 * AGV 接口文档
 *
 * @author zjx
 * @date 2023/04/08
 */
@Slf4j
@Component
public class RCSUtil {

    @Value("${third.agvCreateTaskUrl:}")
    private String agvCreateTaskUrl;

    @Value("${third.agvCancelTaskUrl:}")
    private String agvCancelTaskUrl;

    @Value("${third.agvStatesUrl:}")
    private String agvStatesUrl;

    @Value("${third.queryAckByTaskUrl:}")
    private String queryAckByTaskUrl;

    @Autowired
    BusinDataTaskMapper businDataTaskMapper;

    @Resource
    RedisTemplate redisTemplate;

    @Autowired
    IWcsPlcPropertyService iWcsPlcPropertyService;

    @Autowired
    PLCReadAndWrite plcReadAndWrite;

    @Autowired
    ISysParameterService isysParameterService;

    @Autowired
    IWcsPlcConnectService iWcsPlcConnectService;


    @Autowired
    PlcInit plcInit;


    /**
     * 设置头部信息
     *
     * @return {@code Map<String, String>}
     */
    public Map<String, String> getHeaderMap() {
        Map<String, String> headerMap = new HashMap<>(1);
        headerMap.put("authorization", "mrbase64 mrrest:YWRtaW4mYWRtaW4=");
        return headerMap;
    }


    /**
     * 创建任务
     * wcs系统通过此接口向rcs系统下发创建任务指令
     *
     * @param dto dto
     * @return {@code Result}
     */
    public Result rcsCreateTask(RcsCreateTaskDto dto) {
        String json = JSONObject.toJSONString(dto);
        log.info("向rcs创建任务参数"+json);
        try {
            Map<String, String> headerMap = getHeaderMap();
            String res = HttpRequest.post(agvCreateTaskUrl)
                    .addHeaders(headerMap)
                    .body(json)
                    .execute().body();
            log.info("向rcs创建任务返回：" + res);
            return parseThirdRcsResult(res);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("createTask 方法出错了 = {}", e.getMessage());
            return Result.err().msg(e.getMessage());
        }
    }


    /**
     * 放行任务
     * wcs系统通过此接口向rcs系统下发放行任务指令
     *
     * @param dto dto
     * @return {@code Result}
     */
    public Result queryAck(RcsCreateTaskDto dto) {
        String json = JSONObject.toJSONString(dto);
        try {
            Map<String, String> headerMap = getHeaderMap();
            String res = HttpRequest.post(queryAckByTaskUrl)
                    .addHeaders(headerMap)
                    .body(json)
                    .execute().body();
            return parseThirdRcsResult(res);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("放行 方法出错了 = {}", e.getMessage());
            return Result.err().msg(e.getMessage());
        }
    }

    public Result parseThirdRcsResult(String res) {
        try {
            res = res.trim();
            RcsThirdResult thirdResult = JSONObject.parseObject(res, RcsThirdResult.class);
            if (thirdResult == null) {
                // 添加到异常中去
                return Result.err().msg(res);
            }
            if (!RcsThirdResult.isOk(thirdResult)) {
                return Result.err().msg(res);
            }
            return Result.ok();
        } catch (Exception e) {
            log.error("parseThirdRcsResult res = {} e = {}", res, e);
            return Result.err().msg(res);
        }
    }

    /**
     * 任务取消
     * 上游系统调⽤此接⼝，将已下发待处理的任务取消
     *
     * @param /rest/tasks/del
     * @return {@code Result}
     */
    public Result rcsTaskCancel(RcsCancelTaskDto dto) {
        String json = JSONObject.toJSONString(dto);
        log.info("向rcs任务取消参数：" + json);
        try {
            Map<String, String> headerMap = getHeaderMap();
            String res = HttpRequest.post(agvCancelTaskUrl)
                    .addHeaders(headerMap)
                    .body(json)
                    .execute().body();
            log.info("向rcs任务取消返回：" + res);
            return parseThirdRcsResult(res);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("rcs taskCancel 方法出错了 = {}", e.getMessage());
            return Result.err().msg(e.getMessage());
        }
    }


    /**
     * AGV搬运
     *
     * @param bo
     * @return {@link Result}<{@link Boolean}>
     */
    public Result<Boolean> moveByAGV(AGVMoveBo bo) {
        RcsCreateTaskDto dto = new RcsCreateTaskDto();
        dto.setTaskType(String.valueOf(bo.getTaskType()));
        //库位编号
        List<RcsIdList> idList = new ArrayList<>();
        List<String> points = bo.getPoints();
        for (String point : points) {
            RcsIdList rcsIdList = new RcsIdList();
            log.error(point);
            idList.add(rcsIdList);
        }
         return rcsCreateTask(dto);
//           return Result.ok();
    }

    /**
     * 获取AGV实时状态信息
     *
     * @param singleRobotCode bo
     * @return {@code Result}
     */
    public Result rcsRobotsStates(String singleRobotCode) {
        String json = JSONObject.toJSONString(singleRobotCode);
        try {
            Map<String, String> headerMap = getHeaderMap();
            String res = HttpRequest.post(agvStatesUrl)
                    .addHeaders(headerMap)
                    .body(json)
                    .execute().body();
            //获取AGV状态信息 推送前端及存储数据库及存储redis TODO
            return parseThirdRcsResult(res);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("createTask 方法出错了 = {}", e.getMessage());
            return Result.err().msg(e.getMessage());
        }
    }


    /**
     * AGV上报任务每一步状态
     *
     * @param bo bo
     * @return {@code Result}
     */
    public Result<AGVStatesBo> uploadAgvTaskStatus(AGVUploadStatusBo bo) {



        Long plcId = (Long) redisTemplate.opsForValue().get(RedisConstant.redistaskPlc + bo.getTaskId().toString());

        //根据plcId获取plc信息
        WcsPlcConnect wcsplc = (WcsPlcConnect) redisTemplate.opsForValue().get(RedisConstant.redisPlcConnect + plcId);

        List<WcsPlcProperty> propertyList = iWcsPlcPropertyService.getWcsPlcPropertyByPlcId(plcId);
        String writeTaskId = "";
        String valueType = "";
        for (WcsPlcProperty wcsPlcProperty : propertyList) {
            //AGV取走完成
            if (wcsPlcProperty.getPointType().equals("7")) {
                writeTaskId = wcsPlcProperty.getAddress();
                valueType = wcsPlcProperty.getValueType();
            }
        }

        Map<String, String> writeMap = new HashMap<>(1);
        writeMap.put(valueType, "true");
        Map<String, Object> allMap = new HashMap<>(1);
        allMap.put(writeTaskId, writeMap);

        Map<String, String> readMap = new HashMap<>(1);
        readMap.put(writeTaskId, valueType);

        PlcOperate plcOperate = plcInit.getPlcOperateByIp(wcsplc.getPlcIp());
        //回填plc状态
        PLCReadAndWrite plcReadAndWrite = new PLCReadAndWrite();
        //首先读取任务编号，同目前返回的任务编号是否一致，如果一致则回填状态；
        Map<String, Object> stringObjectMap = plcReadAndWrite.readPlcData(plcOperate, JSONObject.toJSONString(readMap));
        //if(stringObjectMap.get(writeTaskId).equals(bo.getTaskId())){
        plcReadAndWrite.execWrite(plcOperate, JSONObject.toJSONString(allMap));
        //}
        return Result.ok();
    }


    /**
     * AGV上报任务每一步状态
     *
     * @param
     * @return {@code Result}
     */
    public Result uploadAgvTaskStatusTmp(AGVUploadStatusBo bo) {
        return Result.ok();
    }
}
