package org.wcs.business.pub;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.wcs.constant.ConstantData;
import org.wcs.constant.enums.http.ConveyCallBackStatusEnum;
import org.wcs.constant.enums.http.StockCallBackStatusEnum;
import org.wcs.model.bo.tuple.Tuple2;
import org.wcs.model.dto.client.*;
import org.wcs.model.po.app.AppConveyTask;
import org.wcs.model.po.app.AppEtagTask;
import org.wcs.model.po.app.AppStockComposeTask;
import org.wcs.plugin.webHttpClient.WebHttpClient;
import org.wcs.plugin.webHttpClient.model.HttpRequest;
import org.wcs.plugin.webHttpClient.model.HttpResponse;
import org.wcs.utils.AppStringUtils;
import org.wcs.utils.AppUUIDUtils;

/**
 * 标准上报上位系统类 ---- 标准文档里发送给上位系统的方法都在这里
 */
@Slf4j
public class ReportStandard {

    // 仓库任务上报状态地址键，用任务来源拼接此字符串查找上位系统地址
    private static final String stockTaskCallBackAddressKey = "_STOCK_TASK_STATUS_CALLBACK";
    // 输送线任务上报状态地址键，用任务来源拼接此字符串查找上位系统地址
    private static final String conveyTaskCallBackAddressKey = "_CONVEY_TASK_STATUS_CALLBACK";
    // 贴标任务上报状态地址键，用任务来源拼接此字符串查找上位系统地址
    private static final String etagTaskCallBackAddressKey = "_ETAG_TASK_STATUS_CALLBACK";
    // 仓库任务申请地址键，用任务点绑定的系统拼接此字符串查找上位系统地址
    private static final String stockLoginRequestAddressKey = "_STOCK_LOGIN_REQ";

    /**
     * 上报仓库任务状态
     * @param status 状态
     * @param composeTask 仓库任务
     * @return <错误信息，响应数据 >
     */
    public static Tuple2<String, String> stockTaskReport(StockCallBackStatusEnum status, AppStockComposeTask composeTask) {
        return stockTaskReport(status, composeTask, status.getMessage(), "");
    }

    /**
     * 上报仓库任务状态
     * @param status 状态
     * @param composeTask 仓库任务
     * @param message 消息
     * @return <错误信息，响应数据 >
     */
    public static Tuple2<String, String> stockTaskReport(StockCallBackStatusEnum status, AppStockComposeTask composeTask, String message) {
        return stockTaskReport(status, composeTask, message, "");
    }

    /**
     * 上报仓库任务状态
     * @param status 状态
     * @param composeTask 仓库任务
     * @param message 消息
     * @param destination 目标位置
     * @return <错误信息，响应数据 >
     */
    public static Tuple2<String, String> stockTaskReport(StockCallBackStatusEnum status, AppStockComposeTask composeTask, String message, String destination) {
        if(composeTask.getTaskSource().equals(ConstantData.SYSTEM_NAME)) {
            return new Tuple2<>(null, "内部任务不上报"); // WCS 系统自己创建的不执行上传动作
        }
        StockTaskStatusUploadReq stockTaskStatusUploadReq = new StockTaskStatusUploadReq();
        stockTaskStatusUploadReq.setTaskId(composeTask.getUpperTaskId());
        stockTaskStatusUploadReq.setTaskStatus(status.getCode());
        stockTaskStatusUploadReq.setDestination(destination);
        stockTaskStatusUploadReq.setVehicleNo(composeTask.getVehicleNo());
        stockTaskStatusUploadReq.setMessage(message);
        /* 构造请求体 */
        HttpRequest httpRequest = HttpRequest.buildStart().post().setAddressKey(composeTask.getTaskSource() + stockTaskCallBackAddressKey)
                .setBody(AppStringUtils.objectToString(stockTaskStatusUploadReq));
        if(StockCallBackStatusEnum.completeStatus().contains(status)) {
            httpRequest = httpRequest.autoRetry(); // 结束状态的必须重试发送
        }
        httpRequest = httpRequest.buildEnd();
        HttpResponse httpResponse = WebHttpClient.httpRequest(httpRequest);
        log.info("仓库任务：{} 任务状态上报上位系统，请求结果：{}", composeTask.getUpperTaskId(), httpResponse.isSuccess());
        if(!httpResponse.isBaseDataError() && httpResponse.isSuccess()) {
            return new Tuple2<>(null, httpResponse.getResponseText());
        }
        String errText = "";
        if(AppStringUtils.isNotEmpty(httpResponse.getErrText())) {
            errText += httpResponse.getErrText();
        }
        if(httpResponse.getException() != null) {
            errText += httpResponse.getException().getMessage();
        }
        return new Tuple2<>(errText, null);
    }

    /**
     * 仓库任务申请
     * @param sysName 系统名称
     * @param vehicleNo 车辆编号
     * @param origin 源点
     * @return <错误信息，响应数据 >
     */
    public static Tuple2<String, StockLoginDataResp> stockLoginRequest(String sysName, String vehicleNo, String origin) {
        return stockLoginRequest(sysName, vehicleNo, origin, 0, 0, 0, 0, 0);
    }

    /**
     * 仓库任务申请
     * @param sysName 系统名称
     * @param vehicleNo 车辆编号
     * @param origin 源点
     * @param size 尺寸
     * @param weight 重量
     * @return <错误信息，响应数据 >
     */
    public static Tuple2<String, StockLoginDataResp> stockLoginRequest(String sysName, String vehicleNo, String origin, Integer size, Integer weight) {
        return stockLoginRequest(sysName, vehicleNo, origin, size, weight, 0, 0, 0);
    }


   /**
    * 仓库任务申请
    * @param sysName 系统名称
    * @param vehicleNo 车辆编号
    * @param origin 源点
    * @param size 尺寸
    * @param weight 重量
    * @param length 长度
    * @param width 宽度
    * @param height 高度
    * @return <错误信息，响应数据 >
    */
    public static Tuple2<String, StockLoginDataResp> stockLoginRequest(String sysName, String vehicleNo, String origin, Integer size, Integer weight, Integer length, Integer width, Integer height) {
        // 请求上位系统
        StockLoginReq stockLoginReq = new StockLoginReq();
        stockLoginReq.setRequestId(AppUUIDUtils.getNewUUID());
        stockLoginReq.setVehicleNo(vehicleNo);
        stockLoginReq.setLocation(origin);
        stockLoginReq.setSize(size);
        stockLoginReq.setLength(length);
        stockLoginReq.setWidth(width);
        stockLoginReq.setHeight(height);
        stockLoginReq.setWeight(weight);
        HttpRequest httpRequest = HttpRequest.buildStart()
                .post()
                .setAddressKey(sysName + stockLoginRequestAddressKey)
                .setBody(AppStringUtils.objectToString(stockLoginReq))
                .buildEnd();
        HttpResponse httpResponse = WebHttpClient.httpRequest(httpRequest);
        if(!httpResponse.isSuccess()) {
            log.info("点位：{} 申请仓储任务失败，异常信息：{}", origin, httpResponse.getException().toString());
            return new Tuple2<>("请求服务器失败", null);
        }
        String responseText = httpResponse.getResponseText();
        UpperSystemDataResponse<StockLoginDataResp> upperSystemDataResponse = JSONObject.parseObject(responseText, new TypeReference<>(){});
        if(upperSystemDataResponse == null) {
            log.info("点位：{} 申请仓储任务失败，返回的数据无法解析，返回信息：{}", origin, responseText);
            return new Tuple2<>("请求返回的任务数据无法解析", null);
        }
        if(!upperSystemDataResponse.isOk()) {
            log.info("点位：{} 申请仓储任务失败，上位返回信息：{}", origin, upperSystemDataResponse.getMessage());
            return new Tuple2<>(upperSystemDataResponse.getMessage(), null);
        }
        log.info("点位：{} 申请仓储任务成功，信息：{}", origin, upperSystemDataResponse.getMessage());
        return new Tuple2<>(null, upperSystemDataResponse.getReturnData());
    }

    /**
     * 输送任务上报
     * @param status 状态
     * @param conveyTask 配送任务
     * @param message 错误信息
     * @return <错误信息，响应数据 >
     */
    public static Tuple2<String, String> conveyTaskReport(ConveyCallBackStatusEnum status, AppConveyTask conveyTask, String message) {
        return conveyTaskReport(status, conveyTask, message, null);
    }

    /**
     * 输送任务上报
     * @param status 状态
     * @param conveyTask 配送任务
     * @param message 错误信息
     * @param arriveLocation 到达点
     * @return <错误信息，响应数据 >
     */
    public static Tuple2<String, String> conveyTaskReport(ConveyCallBackStatusEnum status, AppConveyTask conveyTask, String message, String arriveLocation) {
        if(conveyTask.getTaskSource().equals(ConstantData.SYSTEM_NAME)) {
            return new Tuple2<>(null, "内部任务不上报");
        }
        ConveyTaskStatusUploadReq conveyTaskStatusUploadReq = new ConveyTaskStatusUploadReq();
        conveyTaskStatusUploadReq.setTaskId(conveyTask.getTaskId());
        conveyTaskStatusUploadReq.setTaskType(conveyTask.getTaskType());
        conveyTaskStatusUploadReq.setTaskStatus(status.getCode());
        conveyTaskStatusUploadReq.setVehicleNo(conveyTask.getVehicleNo());
        conveyTaskStatusUploadReq.setArriveLocation(arriveLocation);
        conveyTaskStatusUploadReq.setMessage(message);
        HttpRequest httpRequest = HttpRequest.buildStart().post().setAddressKey(conveyTask.getTaskSource() + conveyTaskCallBackAddressKey)
                .setBody(AppStringUtils.objectToString(conveyTaskStatusUploadReq));
        if(ConveyCallBackStatusEnum.completeStatus().contains(status)) {
            httpRequest = httpRequest.autoRetry();
        }
        httpRequest = httpRequest.buildEnd();
        HttpResponse httpResponse = WebHttpClient.httpRequest(httpRequest);
        if(httpResponse.isBaseDataError()) {
            return new Tuple2<>(httpResponse.getErrText(), null);
        }
        if(!httpResponse.isSuccess()) {
            String errText = httpResponse.getErrText();
            if(httpResponse.getException() != null) {
                errText += httpResponse.getException().getMessage();
            }
            return new Tuple2<>(errText, null);
        }
        return new Tuple2<>(null, httpResponse.getResponseText());
    }

    /**
     * 电子标签任务上报
     * @param etagTask 贴标任务
     * @param confirmNum 确认数量
     * @param confirmPerson 确认人
     * @return <错误信息，响应数据 >
     */
    public static Tuple2<String, String> etagTaskReport(AppEtagTask etagTask, Integer confirmNum, String confirmPerson) {
        if(etagTask.getTaskSource().equals(ConstantData.SYSTEM_NAME)) {
            return new Tuple2<>(null, "内部任务不上报");
        }
        EtagTaskStatusUploadReq etagTaskStatusUploadReq = new EtagTaskStatusUploadReq();
        etagTaskStatusUploadReq.setTaskId(etagTask.getTaskId());
        etagTaskStatusUploadReq.setConfirmNum(confirmNum);
        etagTaskStatusUploadReq.setConfirmPerson(confirmPerson);
        HttpRequest httpRequest = HttpRequest.buildStart().post().setAddressKey(etagTask.getTaskSource() + etagTaskCallBackAddressKey)
                .setBody(AppStringUtils.objectToString(etagTaskStatusUploadReq)).autoRetry().buildEnd();
        HttpResponse httpResponse = WebHttpClient.httpRequest(httpRequest);
        if(httpResponse.isBaseDataError()) {
            return new Tuple2<>(httpResponse.getErrText(), null);
        }
        if(!httpResponse.isSuccess()) {
            String errText = httpResponse.getErrText();
            if(httpResponse.getException() != null) {
                errText += httpResponse.getException().getMessage();
            }
            return new Tuple2<>(errText, null);
        }
        return new Tuple2<>(null, httpResponse.getResponseText());
    }



}
