using System;
using System.Collections.Generic;
using System.Configuration;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using MyLog4Net;

namespace MisDataSaveDate
{
    /// <summary>
    /// AGV API调用封装类
    /// </summary>
    public static class AgvApiHelper
    {
        #region 常量定义

        /// <summary>
        /// 空托放置区库区号
        /// </summary>
        public const string EMPTY_PALLET_PARTITION = "15";

        /// <summary>
        /// 成品送料区库区号
        /// </summary>
        public const string PRODUCT_PARTITION = "11";

        /// <summary>
        /// 当前产品下线区库区号
        /// </summary>
        public const string OFFLINE_PARTITION = "10";

        /// <summary>
        /// 下线工位号
        /// </summary>
        public const string OFFLINE_OP_NAME = "A40";

        /// <summary>
        /// 下线库位号
        /// </summary>
        public const int OFFLINE_POSITION_CODE = 30;

        /// <summary>
        /// PLC托盘状态点位
        /// </summary>
        public const int PLC_TRAY_STATUS = 63;

        /// <summary>
        /// PLC物料状态点位
        /// </summary>
        public const int PLC_MATERIAL_STATUS = 64;

        #endregion

        #region 数据模型

        /// <summary>
        /// API响应基础类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class ApiResponse<T>
        {
            public bool Result { get; set; }
            public T Data { get; set; }
            public string ErrMsg { get; set; }
        }

        /// <summary>
        /// 库区信息
        /// </summary>
        public class PartitionInfo
        {
            public string PartitionCode { get; set; }
            public string PartitionName { get; set; }
        }

        /// <summary>
        /// 库位信息
        /// </summary>
        public class StockInfo
        {
            public string StockCode { get; set; }
            public string StockName { get; set; }
            public bool StockStatus { get; set; }
            public string PalletCode { get; set; }
            public string EngineNo { get; set; }
            public string SortNo { get; set; }
            public string TaskId { get; set; }
        }

        /// <summary>
        /// 创建任务请求
        /// </summary>
        public class CreateTaskRequest
        {
            public string taskId { get; set; }
            public string pickPosition { get; set; }
            public string dropPosition { get; set; }
        }

        /// <summary>
        /// 更新库位信息请求
        /// </summary>
        public class UpdateStockRequest
        {
            public string StockCode { get; set; }
            public bool StockStatus { get; set; }
            public string PalletCode { get; set; }
            public string EngineNo { get; set; }
            public string SortNo { get; set; }
            public string TaskId { get; set; }
        }

        #endregion

        #region 配置和HTTP工具方法

        /// <summary>
        /// 获取AGV API地址
        /// </summary>
        /// <returns></returns>
        private static string GetAgvApiUrl()
        {
            return ConfigurationManager.AppSettings["agvApi"] ?? "";
        }

        /// <summary>
        /// 发送POST请求
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url">API方法名</param>
        /// <param name="data">请求参数</param>
        /// <returns></returns>
        private static async Task<ApiResponse<T>> PostRequestAsync<T>(string url, object data)
        {
            try
            {
                using (var client = new HttpClient())
                {
                    client.Timeout = TimeSpan.FromSeconds(30);

                    var requestBody = new
                    {
                        url = url,
                        data = data
                    };

                    var json = JsonConvert.SerializeObject(requestBody);
                    var content = new StringContent(json, Encoding.UTF8, "application/json");

                    var response = await client.PostAsync(GetAgvApiUrl(), content);
                    var responseJson = await response.Content.ReadAsStringAsync();

                    // 只记录关键操作的API调用日志
                    if (url == "createTask" || !response.IsSuccessStatusCode)
                    {
                        MyLogHelper.Info("AGV API调用", $"请求: {url} 参数: {json} 响应: {responseJson}");
                    }

                    if (response.IsSuccessStatusCode)
                    {
                        // 第一次解析，获取外层响应
                        var apiResult = JsonConvert.DeserializeObject<ApiResponse<string>>(responseJson);
                        if (apiResult != null && apiResult.Result)
                        {
                            // 第二次解析，获取内层响应
                            var innerResponse = JsonConvert.DeserializeObject<ApiResponse<T>>(apiResult.Data);
                            if (innerResponse != null && innerResponse.Result)
                            {
                                return new ApiResponse<T>
                                {
                                    Result = true,
                                    Data = innerResponse.Data,
                                    ErrMsg = ""
                                };
                            }
                            else
                            {
                                MyLogHelper.Error("AGV API调用", $"内层API返回失败: {innerResponse?.ErrMsg}");
                                return new ApiResponse<T>
                                {
                                    Result = false,
                                    Data = default(T),
                                    ErrMsg = innerResponse?.ErrMsg ?? "内层API调用失败"
                                };
                            }
                        }
                        else
                        {
                            MyLogHelper.Error("AGV API调用", $"外层API返回失败: {apiResult?.ErrMsg}");
                            return new ApiResponse<T>
                            {
                                Result = false,
                                Data = default(T),
                                ErrMsg = apiResult?.ErrMsg ?? "外层API调用失败"
                            };
                        }
                    }
                    else
                    {
                        MyLogHelper.Error("AGV API调用", $"HTTP请求失败: {response.StatusCode} {responseJson}");
                        return new ApiResponse<T>
                        {
                            Result = false,
                            Data = default(T),
                            ErrMsg = $"HTTP请求失败: {response.StatusCode}"
                        };
                    }
                }
            }
            catch (Exception ex)
            {
                MyLogHelper.Error("AGV API调用", $"异常: {ex.Message}");
                return new ApiResponse<T>
                {
                    Result = false,
                    Data = default(T),
                    ErrMsg = ex.Message
                };
            }
        }

        #endregion

        #region AGV API方法

        /// <summary>
        /// 获取库区列表
        /// </summary>
        /// <returns></returns>
        public static async Task<List<PartitionInfo>> GetPartitionListAsync()
        {
            try
            {
                var response = await PostRequestAsync<List<PartitionInfo>>("getPartitionList", new { });
                return response.Result ? response.Data : new List<PartitionInfo>();
            }
            catch (Exception ex)
            {
                MyLogHelper.Error("获取库区列表", $"异常: {ex.Message}");
                return new List<PartitionInfo>();
            }
        }

        /// <summary>
        /// 获取库位列表
        /// </summary>
        /// <param name="partitionCode">库区编号</param>
        /// <returns></returns>
        public static async Task<List<StockInfo>> GetStockListAsync(string partitionCode)
        {
            try
            {
                var response = await PostRequestAsync<List<StockInfo>>("getStockList", new { PartitionCode = partitionCode });
                if (response.Result)
                {
                    // 移除常规获取库位的日志，避免刷屏
                    return response.Data ?? new List<StockInfo>();
                }
                else
                {
                    MyLogHelper.Error("获取库位列表", $"库区{partitionCode}获取失败: {response.ErrMsg}");
                    return new List<StockInfo>();
                }
            }
            catch (Exception ex)
            {
                MyLogHelper.Error("获取库位列表", $"异常: {ex.Message}");
                return new List<StockInfo>();
            }
        }

        /// <summary>
        /// 创建AGV任务
        /// </summary>
        /// <param name="taskId">任务ID</param>
        /// <param name="pickPosition">起始位置</param>
        /// <param name="dropPosition">终点位置</param>
        /// <returns></returns>
        public static async Task<bool> CreateTaskAsync(string taskId, string pickPosition, string dropPosition)
        {
            try
            {
                var request = new CreateTaskRequest
                {
                    taskId = taskId,
                    pickPosition = pickPosition,
                    dropPosition = dropPosition
                };

                var response = await PostRequestAsync<object>("createTask", request);
                if (response.Result)
                {
                    MyLogHelper.Info("创建AGV任务", $"任务创建成功: {taskId} 从{pickPosition}到{dropPosition}");
                    return true;
                }
                else
                {
                    MyLogHelper.Error("创建AGV任务", $"任务创建失败: {response.ErrMsg}");
                    return false;
                }
            }
            catch (Exception ex)
            {
                MyLogHelper.Error("创建AGV任务", $"异常: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 更新库位信息
        /// </summary>
        /// <param name="request">更新请求</param>
        /// <returns></returns>
        public static async Task<bool> UpdateStockInfoAsync(UpdateStockRequest request)
        {
            try
            {
                var response = await PostRequestAsync<object>("updateStockInfo", request);
                if (response.Result)
                {
                    MyLogHelper.Info("更新库位信息", $"库位{request.StockCode}更新成功");
                    return true;
                }
                else
                {
                    MyLogHelper.Error("更新库位信息", $"库位{request.StockCode}更新失败: {response.ErrMsg}");
                    return false;
                }
            }
            catch (Exception ex)
            {
                MyLogHelper.Error("更新库位信息", $"异常: {ex.Message}");
                return false;
            }
        }

        #endregion

        #region 业务逻辑方法

        /// <summary>
        /// 获取空库位(无托盘无物料)
        /// </summary>
        /// <param name="partitionCode">库区编号</param>
        /// <returns></returns>
        public static async Task<List<StockInfo>> GetEmptyStocksAsync(string partitionCode)
        {
            var stockList = await GetStockListAsync(partitionCode);
            var emptyStocks = stockList.FindAll(stock =>
                stock.StockStatus == false &&
                string.IsNullOrEmpty(stock.PalletCode) &&
                string.IsNullOrEmpty(stock.TaskId));

            // 只在没有找到空库位时记录警告日志
            if (emptyStocks.Count == 0)
            {
                MyLogHelper.Error("获取空库位", $"库区{partitionCode}没有可用的空库位");
            }
            return emptyStocks;
        }

        /// <summary>
        /// 获取空托盘库位(有托盘无物料)
        /// </summary>
        /// <param name="partitionCode">库区编号</param>
        /// <returns></returns>
        public static async Task<List<StockInfo>> GetEmptyPalletStocksAsync(string partitionCode)
        {
            var stockList = await GetStockListAsync(partitionCode);
            var emptyPalletStocks = stockList.FindAll(stock =>
                stock.StockStatus == false &&
                !string.IsNullOrEmpty(stock.PalletCode) &&
                string.IsNullOrEmpty(stock.TaskId));

            // 只在没有找到空托盘时记录警告日志
            if (emptyPalletStocks.Count == 0)
            {
                MyLogHelper.Error("获取空托盘库位", $"库区{partitionCode}没有可用的空托盘");
            }
            return emptyPalletStocks;
        }

        /// <summary>
        /// 检查库位是否有任务
        /// </summary>
        /// <param name="stockCode">库位编号</param>
        /// <returns></returns>
        public static async Task<bool> CheckStockHasTaskAsync(string stockCode)
        {
            try
            {
                // 通过库位所在的库区来查询
                var partitions = new[] { OFFLINE_PARTITION };

                foreach (var partitionCode in partitions)
                {
                    var stockList = await GetStockListAsync(partitionCode);
                    var stock = stockList.Find(s => s.StockCode == stockCode);
                    if (stock != null)
                    {
                        bool hasTask = !string.IsNullOrEmpty(stock.TaskId);
                        // 移除任务状态检查的日志，避免频繁记录
                        return hasTask;
                    }
                }

                MyLogHelper.Error("检查库位任务", $"未找到库位{stockCode}");
                return false;
            }
            catch (Exception ex)
            {
                MyLogHelper.Error("检查库位任务", $"异常: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 生成产品编号(当前日期时间戳，去掉年份)
        /// </summary>
        /// <returns></returns>
        public static string GenerateProductNumber()
        {
            var now = DateTime.Now;
            return now.ToString("MMddHHmmss");
        }

        #endregion
    }
}