using Newtonsoft.Json;
using Pms.Models;
using ProjectManagementSystem.Common.Service;
using ProjectManagementSystem.Common.Logger;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Pms.DataLibrary.Order;
using ProjectManagementSystem.Common.Models;
using Pms.DataLibrary.Models;
using ProjectManagementSystem.Common.Extenions;
using System.Runtime.CompilerServices;

namespace ProjectManagementSystem.Common.WebApi
{
    /// <summary>
    /// 用于支持PMSV4所有接口信息（需要自行反编译Pms.WebApi.dll查看具体的接口数据）
    /// 数据模型对象依赖Pms.Models.dll
    /// </summary>
    public class PmsApi
    {
        public static bool Status { get; set; } = true;
        private static RestApi<WebMgrResponse> restApi = new RestApi<WebMgrResponse>();

        /// <summary>
        /// Get请求
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="apiName">接口名</param>
        /// <param name="pars">Params参数，可null</param>
        /// <param name="body">Body对象，可null</param>
        /// <param name="data">返回数据对象</param>
        /// <returns>调用成功返回True（code == 20000）</returns>
        public static bool Get<T>(EPmsApi apiName, object pars, object body, out T data)
        {
            data = default(T);
            try
            {
                string url = Common.Function.AppSetting.GetPmsApiUrl(apiName.ToString());
                var res = restApi.Get(url, pars, body, out string content);

                if (res.data != null)
                {
                    var webMgrResponse = JsonConvert.DeserializeObject<WebMgrResponse>(content);
                    data = JsonConvert.DeserializeObject<T>(webMgrResponse.data.ToString());
                }

                if (Status != true)
                {
                    CLog.Instance.SystemLog.WriteInfo("Pms接口恢复");
                }
                Status = true;
                return res.code == 20000;
            }
            catch (Exception ex)
            {
                CLog.Instance.SystemLog.WriteError(ex.Message);
            }

            if (Status != false)
            {
                CLog.Instance.SystemLog.WriteInfo("Pms接口异常");
            }
            Status = false;
            return false;
        }

        /// <summary>
        /// POST请求
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="apiName">接口名</param>
        /// <param name="pars">Params参数，可null</param>
        /// <param name="body">Body对象，可null</param>
        /// <param name="data">返回数据对象</param>
        /// <returns>调用成功返回True（code == 20000）</returns>
        public static bool Post<T>(EPmsApi apiName, object pars, object body, out T data)
        {
            data = default(T);
            try
            {
                string url = Common.Function.AppSetting.GetPmsApiUrl(apiName.ToString());
                var res = restApi.Post(url, pars, body, out string content);
                CLog.Instance.SystemLog.WriteDebug($"Post {url}{Environment.NewLine}  {JsonConvert.SerializeObject(body)}{Environment.NewLine}  {content}");

                if (res.data != null)
                {
                    var webMgrResponse = JsonConvert.DeserializeObject<WebMgrResponse>(content);
                    data = JsonConvert.DeserializeObject<T>(webMgrResponse.data.ToString());
                }

                return res.code == 20000;
            }
            catch (Exception ex)
            {
                CLog.Instance.SystemLog.WriteError(ex.Message);
            }

            return false;
        }

        /// <summary>
        /// Get请求（返回原始数据模型）
        /// </summary>
        /// <param name="apiName"></param>
        /// <param name="pars"></param>
        /// <param name="body"></param>
        /// <returns></returns>
        public static WebMgrResponse Get(EPmsApi apiName, object pars, object body)
        {
            try
            {
                string url = Common.Function.AppSetting.GetPmsApiUrl(apiName.ToString());
                return restApi.Get(url, pars, body, out string content);
            }
            catch (Exception ex)
            {
                CLog.Instance.SystemLog.WriteError(ex.Message);
                return new WebMgrResponse() { message = ex.Message };
            }
        }

        /// <summary>
        /// POST请求（返回原始数据模型）
        /// </summary>
        /// <param name="apiName"></param>
        /// <param name="pars"></param>
        /// <param name="body"></param>
        /// <returns></returns>
        public static WebMgrResponse Post(EPmsApi apiName, object pars, object body)
        {
            try
            {
                string url = Common.Function.AppSetting.GetPmsApiUrl(apiName.ToString());
                var res = restApi.Post(url, pars, body, out string content);
                CLog.Instance.SystemLog.WriteDebug($"Post {url}{Environment.NewLine}  {JsonConvert.SerializeObject(body)}{Environment.NewLine}  {content}");

                return res;
            }
            catch (Exception ex)
            {
                CLog.Instance.SystemLog.WriteError(ex.Message);
                return new WebMgrResponse() { message = ex.Message };
            }
        }

        /// <summary>
        /// 自定义PMS接口Get
        /// </summary>
        /// <param name="apiName"></param>
        /// <param name="pars"></param>
        /// <param name="body"></param>
        /// <returns></returns>
        public static WebMgrResponse CustomApiGet(string apiName, object pars, object body)
        {
            try
            {
                string url = Common.Function.AppSetting.GetPmsApiCustomUrl(apiName);
                return restApi.Get(url, pars, body, out string content);
            }
            catch (Exception ex)
            {
                CLog.Instance.SystemLog.WriteError(ex.Message);
                return new WebMgrResponse() { message = ex.Message };
            }
        }

        /// <summary>
        /// 自定义PMS接口Post
        /// </summary>
        /// <param name="apiName"></param>
        /// <param name="pars"></param>
        /// <param name="body"></param>
        /// <returns></returns>
        public static WebMgrResponse CustomApiPost(string apiName, object pars, object body)
        {
            try
            {
                string url = Common.Function.AppSetting.GetPmsApiCustomUrl(apiName);
                return restApi.Post(url, pars, body, out string content);
            }
            catch (Exception ex)
            {
                CLog.Instance.SystemLog.WriteError(ex.Message);
                return new WebMgrResponse() { message = ex.Message };
            }
        }

        #region 常用PMS4.0接口

        public static List<TaskData> GetTaskList()
        {
            if (!Get(EPmsApi.GetTaskList, null, null, out List<TaskData> taskInfoList)) return null;
            return taskInfoList;
        }
        public static List<TaskInfo> GetHistoryTaskList(DateTime startTime, DateTime endTime)
        {
            if (!Get(EPmsApi.GetHistoryTaskList, new { StartTime = startTime, EndTime = endTime }, null, out List<TaskInfo> taskInfoList)) return null;
            return taskInfoList;
        }

        public static TaskData GetTaskData(string taskId)
        {
            if (!Get(EPmsApi.GetTask, new { TaskID = taskId }, null, out TaskData taskData)) return null;
            if (taskData == null) return null;

            if (!Get(EPmsApi.GetStepList, new { TaskID = taskId }, null, out List<StepData> stepInfoList)) return null;
            if (stepInfoList == null) return null;

            taskData.StepList = stepInfoList;
            return taskData;
        }
        public static List<TaskData> GetTaskDataList()
        {
            if (!Get(EPmsApi.GetTaskList, null, null, out List<TaskData> taskDataList)) return null;
            if (taskDataList == null) return null;

            for (int i = 0; i < taskDataList.Count; i++)
            {
                Get(EPmsApi.GetStepList, new { TaskID = taskDataList[i].TaskID }, null, out List<StepData> stepInfoList);
                taskDataList[i].StepList = stepInfoList;

                if (stepInfoList == null)
                {
                    CLog.Instance.TaskLog.WriteDebug($"{taskDataList[i].TaskID} 获取StepList失败");
                    return null;
                }
            }
            return taskDataList;
        }
        public static TaskData GetHistoryTaskData(string taskId)
        {
            if (!Get(EPmsApi.GetHistoryTaskData, new { TaskID = taskId }, null, out TaskData taskData)) return null;
            return taskData;
        }

        public static List<StepData> GetStepList(string taskId)
        {
            if (!Get(EPmsApi.GetStepList, new { TaskID = taskId }, null, out List<StepData> stepInfoList)) return null;
            return stepInfoList;
        }
        public static List<StepData> GetHistoryStepList(string taskId)
        {
            if (!Get(EPmsApi.GetHistoryStepList, new { TaskID = taskId }, null, out List<StepData> stepInfoList)) return null;
            return stepInfoList;
        }

        public static List<Freight> GetFreights(int agvId)
        {
            if (!Get(EPmsApi.GetFreights, new { carrierIndex = agvId }, null, out List<Freight> agvData)) return null;
            return agvData;
        }

        public static ResultAgvData GetCarrier(int agvId)
        {
            if (!Get(EPmsApi.GetCarrier, new { AgvId = agvId }, null, out ResultAgvData agvData)) return null;
            return agvData;
        }
        public static List<ResultAgvData> GetAllCarrier()
        {
            if (!Get(EPmsApi.GetAllCarrier, null, null, out ResultCarrierInfo carrierInfo)) return null;
            return carrierInfo.ResultAgvDataList;
        }

        public static PropAgvData GetCarrierProp(int agvId)
        {
            if (!Get(EPmsApi.GetCarrier, new { AgvId = agvId }, null, out PropAgvData agvData)) return null;
            return agvData;
        }
        public static List<PropAgvData> GetAllCarrierProp()
        {
            if (!Get(EPmsApi.GetAllCarrier, null, null, out PropCarrierInfo carrierInfo)) return null;
            return carrierInfo.ResultAgvDataList;
        }

        public static List<WarehouseInfo> GetWarehouseListInfo(string warehouseId)
        {
            if (!Get(EPmsApi.GetWarehouseListInfo, new { warehouseId = warehouseId }, null, out List<WarehouseInfo> whouseInfoList)) return null;
            return whouseInfoList;
        }
        public static List<TaskBookInfo> GetTaskBookList()
        {
            if (!Get(EPmsApi.GetTaskBookList, null, null, out List<TaskBookInfo> taskBookInfoList)) return null;
            return taskBookInfoList;
        }
        public static List<OperateInfo> GetOperateList(string name)
        {
            if (!Get(EPmsApi.GetOperateList, new { Name = name }, null, out List<OperateInfo> operateInfoList)) return null;
            return operateInfoList;
        }
        public static List<WarehouseGroupInfo> GetwarehouseGroupType()
        {
            if (!Get(EPmsApi.GetwarehouseGroupType, null, null, out List<WarehouseGroupInfo> warehouseGroupInfoList)) return null;
            return warehouseGroupInfoList;
        }
        public static Dictionary<int, RequestPmsTaskInfo> GetPmsBehavior()
        {
            if (!Get(EPmsApi.GetPmsBehavior, null, null, out Dictionary<int, RequestPmsTaskInfo> requestPmsTaskInfoDict)) return null;

            foreach (var item in requestPmsTaskInfoDict.Keys)
            {
                requestPmsTaskInfoDict[item].agvId = item;
            }
            return requestPmsTaskInfoDict;
        }

        public static bool UpdateStepWarehouse(string taskId, int stepId, string warehouseId)
        {
            var data = new { TaskId = taskId, StepId = stepId, WarehouseId = warehouseId };
            return Post(EPmsApi.UpdateStepWarehouse, null, data, out string info);
        }
        public static bool UpdateStepAgvBehavior(string TaskId, int StepId, bool IsAgvBehavior, int AgvBehavior, int Param1, int Param2, int Param3, int PmsBehavior)
        {
            RequestUpdateStep data = new RequestUpdateStep();
            data.TaskId = TaskId;
            data.StepId = StepId;
            data.IsAgvBehavior = IsAgvBehavior;
            data.AgvBehavior = AgvBehavior;
            data.Param1 = Param1;
            data.Param2 = Param2;
            data.Param3 = Param3;
            data.PmsBehavior = PmsBehavior;

            return Post(EPmsApi.UpdateStepAgvBehavior, null, data, out string info);
        }
        public static bool TaskStepSkip(string taskId, int stepId)
        {
            var data = new { TaskId = taskId, StepId = stepId };
            return Post(EPmsApi.TaskStepSkip, null, data, out RequestTaskStep info);
        }
        public static bool DeleteTaskStep(string taskId, int stepId)
        {
            var data = new { TaskId = taskId, StepId = stepId };
            return Post(EPmsApi.DeleteTaskStep, null, data, out string info);
        }
        public static bool TaskAddStep(string TaskId, int Station, bool IsAgvBehavior, int AgvBehavior, int Param1, int PmsBehavior)
        {
            RequestTaskStep data = new RequestTaskStep();
            data.TaskID = TaskId;
            data.Station = Station;
            data.IsAgvBehavior = IsAgvBehavior;
            data.AgvBehavior = AgvBehavior;
            data.Param1 = Param1;
            data.PmsBehavior = PmsBehavior;

            return Post(EPmsApi.DeleteTaskStep, null, data, out string info);
        }

        public static bool AddOperate(int behavior, string remark)
        {
            RequestOperateInfo requestOperateInfo = new RequestOperateInfo()
            {
                Name = behavior.ToString(),
                Code = behavior,
                isAgvBehavior = false,
                isDelete = true,
                isEdit = true,
                Remark = remark
            };

            return Post(EPmsApi.AddOperate, null, requestOperateInfo, out string dataString);
        }
        public static bool UpdateOperate(OperateInfo operateInfo)
        {
            return Post(EPmsApi.UpdateOperate, null, operateInfo, out string dataString);
        }
        public static bool AddWarehouse(string wareHouseID, int stationID, int r1 = 0, int r2 = 0, int r3 = 0, string groupId = "")
        {
            var requestInfo = new RequestWarehouseInfo()
            {
                WareHouseID = wareHouseID,
                StationID = stationID,
                RelationStationID1 = r1,
                RelationStationID2 = r2,
                RelationStationID3 = r3,
                GroupId = groupId
            };

            return Post(EPmsApi.AddWarehouse, null, requestInfo, out string dataString);
        }
        public static bool UpdateWarehouse(WarehouseInfo requestInfo)
        {
            return Post(EPmsApi.UpdateWarehouse, null, requestInfo, out string dataString);
        }

        public static bool CarrierPause(int agvId)
        {
            return Get(EPmsApi.CarrierPause, new { carrierIndex = agvId }, null, out string data);
        }
        public static bool CarrierResume(int agvId)
        {
            return Get(EPmsApi.CarrierResume, new { carrierIndex = agvId }, null, out string data);
        }
        public static bool SetCarrierLogicBits(int agvId, int bit, int value)
        {
            var data = new { AgvID = agvId, Bit = bit, Value = value };
            return Post(EPmsApi.SetCarrierLogicBits, null, data, out int[] info);
        }
        public static bool SetCarrierLogicValues(int agvId, int bit, int[] values)
        {
            var data = new { AgvID = agvId, Bit = bit, Values = values };
            return Post(EPmsApi.SetCarrierLogicValues, null, data, out int[] info);
        }
        public static bool SetTaskPriority(string taskId, int priority)
        {
            var data = new { TaskID = taskId, Priority = priority };
            return Post(EPmsApi.SetTaskPriority, null, data, out string info);
        }
        public static bool SendTransparentData(int agvId, byte[] data)
        {
            var transData = new RequestTransparentData();
            transData.AgvID = agvId;
            transData.Data = data;
            transData.Len = data.Length;

            return Post(EPmsApi.SendTransparentData, null, transData, out string obj);
        }
        public static bool SetPmsBehaviorFinish(string taskId, int agvId, int pmsBehavior)
        {
            var data = new RequestPmsTaskInfo();
            data.agvId = agvId;
            data.TaskId = taskId;
            data.PmsBehavior = pmsBehavior;

            return Post(EPmsApi.SetPmsBehaviorFinish, null, data, out RequestPmsTaskInfo obj);
        }

        public static WebMgrResponse TaskAddResponse(MidTaskInfoEx data)
        {
            data.SerializeParameters();
            return Post(EPmsApi.TaskAdd, null, data);
        }
        public static bool TaskAdd(MidTaskInfoEx data, [CallerMemberName] string logKeyWord = null)
        {
            data.SerializeParameters();
            bool result = Post(EPmsApi.TaskAdd, null, data, out MidTaskInfo midTaskInfo);
            CLog.Instance.GetAgvLog(data.AgvId).WriteInfo(logKeyWord, $"{data.TaskId} {data.ParentTaskId} AGV{data.AgvId} AgvType{data.AgvType} {data.TemplateName} {data.Parameters} 任务添加{result.ToChineseString()}");
            return result;
        }
        public static bool TaskCancel(string taskId)
        {
            var data = new { TaskID = taskId, IsCancelRely = true };
            return Post(EPmsApi.TaskCancel, null, data, out RequestTaskStep info);
        }
        public static bool TaskEnd(string taskId)
        {
            var data = new { TaskID = taskId, IsReleaseAGV = false };
            return Post(EPmsApi.TaskEnd, null, data, out RequestTaskStep info);
        }
        public static bool TaskPause(string taskId)
        {
            return Post(EPmsApi.TaskPause, null, taskId, out string info);
        }
        public static bool TaskResume(string taskId)
        {
            return Post(EPmsApi.TaskResume, null, taskId, out string info);
        }
        public static bool TaskChangeRely(string taskId, string parentTaskId)
        {
            var data = new { TaskID = taskId, ParentTaskID = parentTaskId };
            bool result = Post(EPmsApi.TaskChangeRely, null, data, out RequestTaskStep taskStep);
            //CLog.Instance.TaskLog.WriteInfo($"{taskId} 更改父任务{result.ToChineseString()} {parentTaskId}");
            return result;
        }
        public static bool TaskChangeAssignAGV(string taskId, int agvId)
        {
            var data = new { TaskID = taskId, AgvId = agvId };
            return Post(EPmsApi.TaskChangeAssignAGV, null, data, out string info);
        }
        public static bool TaskStopReceipt()
        {
            return Post(EPmsApi.TaskStopReceipt, null, null, out string data);
        }
        public static bool TaskContinueReceipt()
        {
            return Post(EPmsApi.TaskContinueReceipt, null, null, out string data);
        }

        #endregion

        /// <summary>
        /// 通过反射获取PMS定义的所有接口名
        /// </summary>
        /// <returns></returns>
        public static string GetPmsWebApiNames()
        {
            //文件路径AGVS目录中的Pms.WebApi.dll
            string filePath = @"D:\yangyuyuan\AGVS\AGVS-1.8.25.0\Plugins\PMS\Pms.WebApi.dll";
            string className = "Pms.WebApi.Controllers.AgvController";

            Assembly asm = Assembly.LoadFrom(filePath);
            Type t = asm.GetType(className);
            MethodInfo[] methods = t.GetMethods();
            var names = methods.Select(d => d.Name).ToArray();

            StringBuilder sb = new StringBuilder();
            foreach (var item in names)
            {
                sb.Append(item);
                sb.AppendLine(",");
            }
            return sb.ToString();
        }
    }

    public enum EPmsApi
    {
        GetPmsVersion,
        GetPmsBehavior,
        SetPmsBehaviorFinish,
        GetTaskgroupList,
        UpdateTaskgroup,
        GetCustombehaviorList,
        UpdateTaskgroupName,
        DeleteTaskgroupName,
        RemoveTaskgroup,
        DissolveTaskgroup,
        DeleteTaskStep,
        TaskEnd,
        TaskStepSkip,
        TaskAddStep,
        TaskChangeRely,
        AddWarehouseGroup,
        UpdateWarehouseGroupByGroupId,
        AppendWarehouseGroupList,
        DeleteWarehouseGroup,
        UpdateWarehouseGroup,
        UpdateWarehouseGroupList,
        GetWarehouseGroupList,
        DeleteWarehouseGroupByType,
        GetallAgvOperateList,
        GetwarehouseGroupType,
        GetEquipmentInfo,
        SetTaskPriority,
        SendTransparentData,
        GetOccupiedPoint,
        SetTaskCancelNoticeEvent,
        GetTaskCancelNoticeEvent,
        CarrierPause,
        CarrierResume,
        GetCarrierLogicValues,
        SetCarrierLogicValues,
        SetCarrierLogicBits,
        OrderAdd,
        OrderCreate,
        OrderCancel,
        TaskStepIsCanRun,
        TaskChangeAGV,
        TaskChangeAssignAGV,
        TaskAppend,
        TaskAdd,
        TaskCancel,
        GetOrderInfo,
        GetTaskData,
        GetTask,
        GetTaskList,
        GetStepList,
        GetTaskCount,
        GetHistoryOrderData,
        GetHistoryOrderDataList,
        GetHistoryTask,
        GetHistoryTaskList,
        GetHistoryTaskData,
        GetHistoryTaskDataList,
        GetTaskDataList,
        GetHistoryStepList,
        ThreadschedulingPause,
        ThreadschedulingResume,
        OrderPause,
        GetFreights,
        GetCarrier,
        GetAllCarrier,
        OrderResume,
        TaskPause,
        TaskStopReceipt,
        TaskContinueReceipt,
        TaskResume,
        GetOrderData,
        GetOrderDataList,
        GetTaskBookList,
        AddTaskBook,
        UpdateTaskBook,
        DeleteTaskBook,
        GetTemplateInfo,
        AddTemplate,
        UpdateTemplate,
        UpdateTemplateList,
        DeleteTemplate,
        UpdateStepWarehouse,
        UpdateStepAgvBehavior,
        SetProperties,
        AddWarehouse,
        UpdateWarehouse,
        DeleteWarehouse,
        GetWarehouseListInfo,
        GetAllWarehouseName,
        GetAllTemplateList,
        AddOperate,
        UpdateOperate,
        DeleteOperate,
        GetOperateList,
        AGVExecuteBookTask,
        GetStations,
        GetAgvIds
    }
}
