package com.shkj.wms.utils;

import com.alibaba.fastjson.JSONObject;
import com.shkj.common.core.domain.Result;
import com.shkj.wcs.third.stacker.StkCallUtil;
import com.shkj.wms.bo.LocationMoveBo;
import com.shkj.wms.bo.STKMoveBo;
import com.shkj.wms.enums.ThirdApiTypeEnum;
import com.shkj.wms.service.IBusinOutInPlanService;
import com.shkj.wms.service.IBusinTaskService;
import com.shkj.wms.service.ISysThirdExceptionRequestService;
import com.shkj.wms.vo.OutStockDetailVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

/**
 * wms调用wcs工具
 *
 * @author lch
 * @date 2023/06/09 14:38:36
 */
@Slf4j
@Component
public class WmsCallWcsUtil {


    @Autowired
    private StkCallUtil stkCallUtil;

    @Autowired
    private IBusinTaskService taskService;

    @Autowired
    private ISysThirdExceptionRequestService thirdExceptionRequestService;

    @Autowired
    @Lazy
    private IBusinOutInPlanService businOutInPlanService;


    /**
     * 出库调用  注意重试的意思
     * recover最终失败的处理
     * maxAttempts 最大重试次数
     * backoff 延迟几秒 这里是 第一次重试2秒 第二次4秒 第三次8秒
     * <p>
     * 因为要返回数据 所以不进行Retryable
     *
     * @param vo
     * @param call
     * @return {@link Result}
     */
//    @Async
//    @Retryable(recover = "outStockRecover", maxAttempts = 3, backoff = @Backoff(value = 2000, multiplier = 2))
    public Result outStock(OutStockDetailVo vo, boolean call,Integer layer) {
        try {
            STKMoveBo moveBo = getStkMoveBo(vo);
            moveBo.setLayer(layer);
            Result<Boolean> result = Result.err();
            log.info("outStock 调用入参 = {} call = {}", moveBo, call);
            if (call) {
                log.info("outStock 调用入参 = {}", moveBo);
                // 需要判断是否存在当前其他任务正在执行、或者库存为空的时候也不需要下发
                Result runTask = businOutInPlanService.checkIsRunTask(vo.getOrderNo());
                //返回正常就不需要处理了
                if (Result.isOk(runTask)) {
                    log.info("runTask 结果 = {}", runTask);
                    return runTask;
                }
                result = stkCallUtil.outTask(moveBo);
            }

            thirdExceptionRequestService.addException(vo.getOrderNo().toString(), ThirdApiTypeEnum.wcsOutTask, JSONObject.toJSONString(moveBo),
                    JSONObject.toJSONString(result), Result.isOk(result),null,layer);
            log.info("outStock 调用结果 = {}", result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("出库任务下发失败 = {}", e.getMessage());
            throw new RuntimeException("出库任务下发失败" + e.getMessage());
        }
    }

    public Result callOutStock(OutStockDetailVo vo,Integer layer) {
        try {
            //从哪个位置搬运
            STKMoveBo moveBo = getStkMoveBo(vo);
            moveBo.setLayer(layer);
            log.info("callOutStock 调用入参 = {}", moveBo);
            //给堆垛机下搬运命令
            Result<Boolean> result = stkCallUtil.outTask(moveBo);
            //记录结果到是否正常，异常要轮询执行
            thirdExceptionRequestService.addException(vo.getOrderNo().toString(), ThirdApiTypeEnum.wcsCallOutStock, JSONObject.toJSONString(moveBo),
                    JSONObject.toJSONString(result), Result.isOk(result),null,layer);
            log.info("outStock 调用结果 = {}", result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("出库任务下发失败 = {}", e.getMessage());
            throw new RuntimeException("出库任务下发失败" + e.getMessage());
        }
    }


//    @Recover
//    public Result<Boolean> outStockRecover(Throwable throwable, OutStockDetailVo vo) {
//        log.info("outStockRecover 进入recover方法...... {}", vo);
//        STKMoveBo moveBo = getStkMoveBo(vo);
//
//        String code = taskService.addTask(vo.getOrderNo(),
//                vo.getOrderNo().toString(),
//                BusinTaskTypeEnum.out.getValue(),
//                TaskStatusEnum.err.getValue(),
//                null,
//                "下发任务" + vo.getLocationCode(),
//                null,
//                vo.getBranchId(),
//                throwable.getMessage(),
//                ThirdApiTypeEnum.wcsOutTask);
//        thirdExceptionRequestService.addException(code, ThirdApiTypeEnum.wcsOutTask, JSONObject.toJSONString(moveBo),
//                throwable.getMessage(), false);
//        return Result.err().msg(throwable.getMessage());
//    }

    private STKMoveBo getStkMoveBo(OutStockDetailVo vo) {
        STKMoveBo moveBo = new STKMoveBo();
        moveBo.setTaskId(vo.getOrderNo());
        moveBo.setFromRow(vo.getLocationRow());
        moveBo.setFromColumn(vo.getLocationColumn());
        moveBo.setFromLayer(vo.getLayer());
        return moveBo;
    }


    /**
     * 出库调用  注意重试的意思
     * recover最终失败的处理
     * maxAttempts 最大重试次数
     * backoff 延迟几秒 这里是 第一次重试2秒 第二次4秒 第三次8秒
     *
     * @param vo
     * @return {@link Result}
     */
//    @Async
//    @Retryable(recover = "locationAdjustmentRecover", maxAttempts = 3, backoff = @Backoff(value = 2000, multiplier = 2))
    public Result locationAdjustment(LocationMoveBo vo) {
        try {
            STKMoveBo moveBo = getStkMoveBo(vo);

            Result<Boolean> result = stkCallUtil.locationAdjustment(moveBo);
            thirdExceptionRequestService.addException(vo.getTaskId().toString(), ThirdApiTypeEnum.wcsMoveLocationTask, JSONObject.toJSONString(moveBo),
                    JSONObject.toJSONString(result), true,null,null);
            return Result.ok();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("货位调整下发失败 = {}", e.getMessage());
            throw new RuntimeException("货位调整下发失败" + e.getMessage());
        }
    }

    private STKMoveBo getStkMoveBo(LocationMoveBo vo) {
        STKMoveBo moveBo = new STKMoveBo();
        moveBo.setTaskId(vo.getTaskId());
        moveBo.setFromRow(vo.getFromRow());
        moveBo.setFromColumn(vo.getFromColumn());
        moveBo.setFromLayer(vo.getFromLayer());
        moveBo.setToRow(vo.getToRow());
        moveBo.setToColumn(vo.getToColumn());
        moveBo.setToLayer(vo.getToLayer());
        return moveBo;
    }


//    @Recover
//    public Result<Boolean> locationAdjustmentRecover(Throwable throwable, LocationMoveBo vo) {
//        log.info("locationAdjustmentRecover 进入recover方法...... {}", vo);
//        STKMoveBo moveBo = getStkMoveBo(vo);
//
//        String code = taskService.addTask(moveBo.getTaskId(),
//                moveBo.getTaskId().toString(),
//                BusinTaskTypeEnum.move.getValue(),
//                TaskStatusEnum.err.getValue(),
//                null,
//                "货位调整" + vo.getFromLocationCode() + "=>" + vo.getToLocationCode(),
//                null,
//                vo.getBranchId(),
//                throwable.getMessage(),
//                ThirdApiTypeEnum.wcsMoveLocationTask);
//        thirdExceptionRequestService.addException(code, ThirdApiTypeEnum.wcsMoveLocationTask, JSONObject.toJSONString(moveBo),
//                throwable.getMessage(), false);
//        return Result.err().msg(throwable.getMessage());
//    }


}
