using ServiceCenter;
using ServiceCenter.Extensions;
using ServiceCenter.Logs;
using ServiceCenter.Redis;
using ServiceCenter.WebApi;
using WCS.WorkEngineering.Extensions;
using WCS.WorkEngineering.WebApi.Models.WCS.Response;
using WCS.WorkEngineering.WebApi.Models.WMS.Request;
using WCS.WorkEngineering.WebApi.Models.WMS.Response;
using wms.dto;
using wms.dto.request;
using wms.dto.request.fj;
using wms.dto.response.fj;
using FJBuildEmptyPalletsStockRequest = WCS.WorkEngineering.WebApi.Models.WMS.Request.FJBuildEmptyPalletsStockRequest;
using FJEnteMainLineRequest = WCS.WorkEngineering.WebApi.Models.WMS.Request.FJEnteMainLineRequest;
using GetTunnelPriorityListRequest = WCS.WorkEngineering.WebApi.Models.WMS.Request.GetTunnelPriorityListRequest;
using ResponseStatusCodeEnum = WCS.WorkEngineering.WebApi.Models.WMS.Response.ResponseStatusCodeEnum;
using TaskBusType = WCS.WorkEngineering.WebApi.Models.WMS.Request.TaskBusType;

namespace WCS.WorkEngineering.WebApi.Controllers
{
    /// <summary>
    /// AWMS相关接口控制器
    /// </summary>

    public static class WmsApi
    {
        private static string _wmsUrl = null!;
        private static string _wareHouseId = null!;

        /// <summary>
        ///  WMS URL
        /// </summary>
        public static string WmsUrl
        {
            get
            {
                _wmsUrl ??= RedisHub.Default.Check("WMSUrl")!;
                if (string.IsNullOrEmpty(_wmsUrl))
                {
                    throw new KnownException($"请在Redis配置WMSUrl", LogLevelEnum.High);
                }
                return _wmsUrl;
            }
        }

        /// <summary>
        /// 仓库编号
        /// </summary>
        public static string wareHouseId = ServiceHub.WarehouseName;

        /// <summary>
        ///  上传重量等信息
        /// </summary>
        /// <param name="taskCode">任务号</param>
        /// <param name="weight">rfid</param>
        /// <returns></returns>
        public static SRes WcsUploadInfo(int taskCode, decimal weight) => WcsUploadInfo(taskCode, weight, "");

        /// <summary>
        ///  上传重量等信息
        /// </summary>
        /// <param name="taskCode">任务号</param>
        /// <param name="RFID">重量</param>
        /// <returns></returns>
        public static SRes WcsUploadInfo(int taskCode, string RFID) => WcsUploadInfo(taskCode, 0, RFID);

        /// <summary>
        ///   上传重量等信息
        /// </summary>
        /// <param name="taskCode">任务号</param>
        /// <param name="weight">重量</param>
        /// <param name="RFID">rfid</param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes WcsUploadInfo(int taskCode, decimal weight, string RFID)
        {
            var res = APICaller.CallApi2<SRes>(WmsUrl + "/api/Hj/WcsUploadInfo", new WcsUploadInfoRequest
            {
                TaskCode = taskCode,
                Weight = weight,
                RFID = RFID
            });

            return res;
        }

        /// <summary>
        ///  变更流向
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static SRes EditorialFlow(FjEditorialFlowRequest req)
        {
            var res = APICaller.CallApi2<SRes>(WmsUrl + "/api/FJ/EditorialFlow", new FjEditorialFlowRequest
            {
                LocCode = req.LocCode,
                TaskId = req.TaskId,
                WareCode = req.WareCode
            });
            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
            {
                throw new KnownException(res.ResMsg, LogLevelEnum.High);
            }
            return res;
        }

        /// <summary>
        ///  分配货位
        /// </summary>
        /// <param name="wcsTaskNum">WMS任务ID</param>
        /// <param name="tunnel">货位</param>
        /// <param name="device">设备号</param>
        /// <param name="size"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static SRes<ApplyStockInLocResponse> GetLocalIn(int wcsTaskNum, string tunnel, string device, int size)
        {
            var res = APICaller.CallApi2<SRes<ApplyStockInLocResponse>>(WmsUrl + "/api/FJ/ApplyStockInLoc", new ApplyStockInLocRequest
            {
                TaskNum = wcsTaskNum,
                TunnelNum = tunnel.GetLastDigit(),
                PickUpEquipmentNo = device.ToString(),
                Height = size
            });

            return res;
        }

        /// <summary>
        ///  分配货位
        /// </summary>
        /// <param name="wcsTaskNum">WMS任务ID</param>
        /// <param name="tunnel">货位</param>
        /// <param name="device">设备号</param>
        /// <param name="size"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static SRes<FJApplyStockInLocResponse> RingApplyStockInLoc(int wcsTaskNum, string tunnel, string device, int size)
        {
            var res = APICaller.CallApi2<SRes<FJApplyStockInLocResponse>>(WmsUrl + "/api/FJ/RingApplyStockInLoc", new FJApplyStockInLocRequest
            {
                TaskNum = wcsTaskNum,
                PickUpEquipmentNo = device,
                Height = size
            });

            return res;
        }

        /// <summary>
        ///  堆垛机出库任务执行完成
        /// </summary>
        /// <param name="taskNum"></param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes<int> SrmPickOutCompleted(int taskNum)
        {
            var res = APICaller.CallApi2<SRes<int>>(WmsUrl + "/api/FJ/SrmPickOutCompleted", new SrmPickOutCompletedRequest
            {
                TaskNum = taskNum,
            });

            return res;
        }

        /// <summary>
        ///  申请出库任务
        /// </summary>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes ApplyEmptyPalletGroupOutStorage(string addto, int tunnel, PalletType type)
        {
            var request = new ApplyStockOutTaskRequest
            {
                Tunnel = tunnel,
                FJPalletType = type,
                AddTo = addto
            };

            var res = APICaller.CallApi2<SRes>(WmsUrl + "/api/fj/ApplyEmptyPalletGroupOutStorage", request);

            return res;
        }

        /// <summary>
        ///  完成任务
        /// </summary>
        /// <param name="taskNo"></param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes<int> CompleteTask(int taskNo)
        {
            var res = APICaller.CallApi2<SRes<int>>(WmsUrl + "/api/fj/CompleteTask", new CompleteTaskRequest
            {
                TaskNum = taskNo,
                OperationType = Models.WMS.Request.CompleteTask.自动完成,
                WCSUpdateName = "WCS"
            });
            return res;
        }

        public static SRes<int> CancelTask(int taskNo)
        {
            var res = APICaller.CallApi2<SRes<int>>(WmsUrl + "/api/fj/CancelTask", new CompleteTaskRequest
            {
                TaskNum = taskNo,
                OperationType = Models.WMS.Request.CompleteTask.自动完成,
                WCSUpdateName = "WCS"
            });
            return res;
        }

        /// <summary>
        ///  处理任务验证接口
        /// </summary>
        /// <param name="taskNo">需要处理的任务进行验证</param>
        /// <param name="state">目标状态</param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes HandleTaskVerify(List<int> taskNo, int state)
        {
            var res = APICaller.CallApi2<SRes>(WmsUrl + "/api/fj/CancelTaskVerify", new CancelTaskVerifyRequest
            {
                TaskNo = taskNo,
                State = state
            });
            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
            {
                throw new KnownException(res.ResMsg, LogLevelEnum.High);
            }
            return res;
        }

        /// <summary>
        ///  处理任务接口
        /// </summary>
        /// <param name="taskNo">处理</param>
        /// <param name="state">目标状态</param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes CarryTaskInfo(List<int> taskNo, int state)
        {
            var res = APICaller.CallApi2<SRes>(WmsUrl + "/api/fj/CarryTaskInfo", new CancelTaskVerifyRequest
            {
                TaskNo = taskNo,
                State = state
            });
            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
            {
                throw new KnownException(res.ResMsg, LogLevelEnum.High);
            }
            return res;
        }

        /// <summary>
        ///  WMS完成或取消任务验证
        /// </summary>
        /// <param name="sRes"></param>
        /// <param name="id"></param>
        /// <param name="type">99完成,106取消</param>
        /// <returns></returns>
        public static SRes? HandleTaskVerify(SRes<HandleTaskResponse> sRes, int id, int type)
        {
            try
            {
                var res = WmsApi.HandleTaskVerify(new List<int>() { id }, type);
                return res;
            }
            catch (Exception ex)
            {
                sRes.ResDataList.Add(new HandleTaskResponse()
                {
                    IsSuccess = false,
                    TaskNo = id,
                    Message = $"WMS错误:{ex.Message}",
                });
                return null;
            }
        }

        /// <summary>
        ///  WMS完成或取消任务执行
        /// </summary>
        /// <param name="sRes"></param>
        /// <param name="id"></param>
        /// <param name="type">99完成,106取消</param>
        /// <returns></returns>
        public static SRes? CarryTaskInfo(SRes<HandleTaskResponse> sRes, int id, int type)
        {
            try
            {
                var res = WmsApi.CarryTaskInfo(new List<int>() { id }, type);
                return res;
            }
            catch (Exception ex)
            {
                sRes.ResDataList.Add(new HandleTaskResponse()
                {
                    IsSuccess = false,
                    TaskNo = id,
                    Message = $"WMS错误:{ex.Message}",
                });
                return null;
            }
        }

        /// <summary>
        ///  一楼扫码入库
        /// </summary>
        /// <param name="codeList">工字轮条码组</param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes? OneFloorWorkerBuildEmptyPalletsStock(OneFloorWorkerBuildEmptyPalletsStockRequest reqDto)
        {
            var res = APICaller.CallApi2<SRes>(WmsUrl + "/api/FJ/OneFloorWorkerBuildEmptyPalletsStock", new OneFloorWorkerBuildEmptyPalletsStockRequest
            {
                PalletCode = reqDto.PalletCode,
                PalletType = reqDto.PalletType,
                StartLoc = reqDto.StartLoc,
                WareCode = reqDto.StartLoc.GetWareCode(),
                PalletNum = "1"
            });
            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
            {
                throw new KnownException(res.ResMsg, LogLevelEnum.High);
            }
            return res;
        }

        /// <summary>
        ///  工字轮/芯股进入主线扫码
        /// </summary>
        /// <param name="reqDto"></param>
        /// <param name="equNo"></param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes EnteMainLine(List<string> reqDto, string equNo)
        {
            var res = APICaller.CallApi<SRes>(WmsUrl + "/api/FJ/EnteMainLine", new FJEnteMainLineRequest
            {
                IShapedWheelCodes = reqDto,
                equNo = equNo
            });
            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
            {
                throw new KnownException(res.ResMsg, LogLevelEnum.High);
            }
            return res;
        }

        /// <summary>
        ///  生成空托盘组盘任务
        /// </summary>
        /// <param name="palletCode"></param>
        /// <param name="loc"></param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes GroupTask(string palletCode, string loc)
        {
            var res = APICaller.CallApi<SRes>(WmsUrl + "/api/FJ/GroupTask", new FJBuildEmptyPalletsStockRequest
            {
                PalletCode = palletCode,
                PalletType = FJPalletType.Pallet09,
                PalletNum = "1",
                StartLoc = loc,
                WareCode = loc.GetWareCode(),
                BusType = TaskBusType.组盘_托盘
            });
            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
            {
                throw new KnownException(res.ResMsg, LogLevelEnum.High);
            }
            return res;
        }

        /// <summary>
        ///  正常结盘
        /// </summary>
        /// <param name="palletCode"></param>
        /// <param name="taskCodes"></param>
        /// <param name="warehouseCode"></param>
        /// <param name="loc"></param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes FinishBingPallet(string palletCode, List<string> taskCodes, string warehouseCode, string loc) => BingPallet(palletCode, taskCodes, warehouseCode, loc, false, "", true, false);

        /// <summary>
        ///  需要二次绑盘的结盘
        /// </summary>
        /// <param name="palletCode"></param>
        /// <param name="taskCodes"></param>
        /// <param name="warehouseCode"></param>
        /// <param name="loc"></param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes SecondaryBingPallet(string palletCode, List<string> taskCodes, string warehouseCode, string loc) => BingPallet(palletCode, taskCodes, warehouseCode, loc, false, "二次绑盘", true, true);

        /// <summary>
        ///  异常结盘
        /// </summary>
        /// <param name="palletCode"></param>
        /// <param name="taskCodes"></param>
        /// <param name="warehouseCode"></param>
        /// <param name="loc"></param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes ForceFinishBingPallet(string palletCode, List<string> taskCodes, string warehouseCode, string loc) => BingPallet(palletCode, taskCodes, warehouseCode, loc, true, "强制码垛结束", true, false);

        /// <summary>
        ///  绑盘
        /// </summary>
        /// <param name="palletCode"></param>
        /// <param name="taskCodes"></param>
        /// <param name="warehouseCode"></param>
        /// <param name="loc"></param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes BingPallet(string palletCode, List<string> taskCodes, string warehouseCode, string loc) => BingPallet(palletCode, taskCodes, warehouseCode, loc, false, "", false, false);

        /// <summary>
        ///  绑盘
        /// </summary>
        /// <param name="palletCode"></param>
        /// <param name="taskCodes"></param>
        /// <param name="warehouseCode"></param>
        /// <param name="loc"></param>
        /// <param name="isFail"></param>
        /// <param name="failReason"></param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes BingPallet(string palletCode, List<string> taskCodes, string warehouseCode, string loc, bool isFail, string failReason, bool isFinish, bool isItHalf)
        {
            var res = APICaller.CallApi2<SRes>(WmsUrl + "/api/FJ/BingPallet", new FJBingPalletRequest
            {
                PalletCode = palletCode,
                TaskCode = taskCodes,
                WarehouseCode = warehouseCode,
                loc = loc,
                IsFail = isFail,
                FailReason = failReason,
                IsFinish = isFinish,
                IsItHalf = isItHalf
            });
            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
            {
                throw new KnownException(res.ResMsg, LogLevelEnum.High);
            }
            return res;
        }

        /// <summary>
        ///  绑盘
        /// </summary>
        /// <param name="warehouseCode"></param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes<int> GetTwoPallet(string warehouseCode, int taskId)
        {
            var res = APICaller.CallApi<SRes<int>>(WmsUrl + "/api/FJ/GetTwoPallet", new FJGetTwoPalletDto
            {
                WarehouseCode = warehouseCode,
                TaskId = taskId
            });
            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
            {
                throw new KnownException(res.ResMsg, LogLevelEnum.High);
            }
            return res;
        }

        /// <summary>
        ///   环形库申请码垛任务
        /// </summary>
        /// <param name="loc"></param>
        /// <param name="robotCode"></param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes ApplyPalletizingStockOut(string loc, string robotCode)
        {
            var res = APICaller.CallApi2<SRes>(WmsUrl + "/api/FJ/ApplyPalletizingStockOut", new wms.dto.request.fj.RingApplyPalletizingStockOutRequest(loc.GetWareCode(), loc, robotCode));
            return res;
        }

        /// <summary>
        /// 码垛工资轮创建异常任务信息
        /// </summary>
        /// <param name="loc">位置</param>
        /// <param name="type">类型</param>
        /// <param name="errType">异常类型</param>
        /// <returns></returns>
        /// <exception cref="KnownException"></exception>
        public static SRes PalletizingCreateseErrorTasks(string loc, string type, int errType = 0)
        {
            var res = APICaller.CallApi2<SRes>(WmsUrl + "/api/FJ/PalletizingCreateseErrorTasks", new Models.WMS.Request.PalletizingCreateseErrorTasksRequest(loc, type, loc.GetWareCode(), errType));

            if (res.ResCode != ResponseStatusCodeEnum.Sucess)
            {
                throw new KnownException(res.ResMsg, LogLevelEnum.High);
            }
            return res;
        }
    }

    public class FJGetTwoPalletDto : BaseRequest
    {
        /// <summary>
        ///  仓库号
        /// </summary>
        public string WarehouseCode { get; set; }

        /// <summary>
        ///  仓库号
        /// </summary>
        public int TaskId { get; set; }
    }

    /// <summary>
    ///  变更流向
    /// </summary>
    public class FjEditorialFlowRequest : BaseRequest
    {
        /// <summary>
        /// 任务号
        /// </summary>
        public int TaskId { get; set; }

        /// <summary>
        /// 目标仓库
        /// </summary>
        public string WareCode { get; set; }

        /// <summary>
        /// 位置
        /// </summary>
        public string LocCode { get; set; }
    }
}