using OASystem.Domain.AesEncryption;
using OASystem.Domain.Attributes;
using OASystem.Domain.Entities.Customer;
using Org.BouncyCastle.Asn1.Pkcs;
using System.Net;
using UAParser;
using static OASystem.API.OAMethodLib.JWTHelper;

namespace OASystem.API.Middlewares
{
    /// <summary>
    /// 指定API操作记录信息
    /// </summary>
    public class RecordAPIOperationMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly HttpClient _httpClient;
        private readonly IConfiguration _config;
        private readonly SqlSugarClient _sqlSugar;

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="next"></param>
        /// <param name="config"></param>
        /// <param name="httpClient"></param>
        /// <param name="sqlSugar"></param>
        public RecordAPIOperationMiddleware(RequestDelegate next, IConfiguration config, HttpClient httpClient, SqlSugarClient sqlSugar)
        {
            _next = next;
            _httpClient = httpClient;
            _config = config;
            _sqlSugar = sqlSugar;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            // 启用请求体流的缓冲,允许多次读取
            context.Request.EnableBuffering();

            // 读取请求体内容
            var requestBodyText = await ReadRequestBody(context.Request);

            // 检查控制器方法是否使用了自定义属性
            var endpoint = context.GetEndpoint();
            var apiLogAttribute = endpoint?.Metadata?.GetMetadata<ApiLogAttribute>();
            if (apiLogAttribute != null)
            {
                var startTime = DateTime.UtcNow;
                int portType = 1, userId = 0, id = 0, status = 0;
                string updatePreData = string.Empty, updateBefData = string.Empty;
                bool param5Bool = false, param6Bool = false;
                try
                {
                    userId = await ReadToken(context);

                    if (!string.IsNullOrEmpty(requestBodyText))
                    {
                        object param1 = string.Empty, param2 = string.Empty, param3 = string.Empty, param4 = string.Empty,
                               param5 = string.Empty, param6 = string.Empty, param7 = string.Empty, param8 = string.Empty;
                        var requestBodyJson = JsonConvert.DeserializeObject<Dictionary<string, object>>(requestBodyText);
                        bool exists1 = requestBodyJson.TryGetValue("portType", out param1);
                        bool exists2 = requestBodyJson.TryGetValue("userId", out param2);
                        bool exists3 = requestBodyJson.TryGetValue("currUserId", out param3);
                        bool exists4 = requestBodyJson.TryGetValue("createUserId", out param4);
                        bool exists5 = requestBodyJson.TryGetValue("id", out param5);
                        bool exists6 = requestBodyJson.TryGetValue("status", out param6);
                        bool exists7 = requestBodyJson.TryGetValue("operationUserId", out param7);
                        bool exists8 = requestBodyJson.TryGetValue("deleteUserId", out param8);

                        if (exists1) int.TryParse(param1.ToString(), out portType);

                        //用户Id处理
                        if (userId < 1)
                        {
                            if (apiLogAttribute.OperationEnum == OperationEnum.Login)
                            {
                                var number = requestBodyJson?["number"].ToString();
                                if (!string.IsNullOrEmpty(number))
                                {
                                    var info = await _sqlSugar.Queryable<Sys_Users>().Where(x => x.IsDel == 0 && x.Number.Equals(number)).FirstAsync();
                                    userId = info.Id;
                                }
                            }
                            else
                            {
                                if (exists2) int.TryParse(param2.ToString(), out userId);
                                else if (exists3) int.TryParse(param3.ToString(), out userId);
                                else if (exists4) int.TryParse(param4.ToString(), out userId);
                                else if (exists7) int.TryParse(param7.ToString(), out userId);
                                else if (exists8) int.TryParse(param8.ToString(), out userId);
                            }
                        }
                        //编辑前数据查询;
                        if (exists5) param5Bool = int.TryParse(param5.ToString(), out id);
                        if (exists6) param6Bool = int.TryParse(param6.ToString(), out status);

                        if (param6Bool)
                        {
                            //  2 修改 
                            if (status == 1) apiLogAttribute.OperationEnum = OperationEnum.Add;
                            else if (status == 2)
                            {
                                apiLogAttribute.OperationEnum = OperationEnum.Edit;
                                updatePreData = await TableInfoToJson(apiLogAttribute.TableName, id);
                            }
                        }
                        else if (param5Bool)
                        {
                            if (apiLogAttribute.OperationEnum != OperationEnum.Del)
                            {
                                //  id > 0 修改 
                                if (id < 1) apiLogAttribute.OperationEnum = OperationEnum.Add;
                                else if (id > 0)
                                {
                                    apiLogAttribute.OperationEnum = OperationEnum.Edit;
                                    updatePreData = await TableInfoToJson(apiLogAttribute.TableName, id);
                                }
                            }
                        }
                    }
                }
                catch (JsonException) { }

                // 保存原始响应体流
                var originalResponseBody = context.Response.Body;

                // 创建一个新的内存流来捕获响应体
                using var responseMemoryStream = new MemoryStream();
                context.Response.Body = responseMemoryStream;

                // 调用下一个中间件
                await _next(context);

                // 重置响应体流的位置
                responseMemoryStream.Position = 0;

                // 读取响应体内容
                var responseBodyText = await ReadResponseBody(responseMemoryStream);

                // 将响应体内容写回原始响应体流
                await responseMemoryStream.CopyToAsync(originalResponseBody);

                //修改后数据查询
                if (param6Bool)
                {
                    //  2 修改 
                    if (status == 2) updateBefData = await TableInfoToJson(apiLogAttribute.TableName, id);
                }
                else if (param5Bool)
                {

                    if (apiLogAttribute.OperationEnum != OperationEnum.Del)
                    {
                        //  id > 0 修改 
                        if (id > 0) updateBefData = await TableInfoToJson(apiLogAttribute.TableName, id);
                    }
                }
                string remoteIp = string.Empty,
                       location = string.Empty;

                // 检查请求头中的X-Forwarded-For,以获取真实的客户端IP地址
                if (context.Request.Headers.ContainsKey("X-Forwarded-For"))
                {
                    remoteIp = context.Request.Headers["X-Forwarded-For"].ToString().Split(',', StringSplitOptions.RemoveEmptyEntries)[0];
                    //_logger.LogInformation($"IP:{remoteIp}");
                }
                else
                {
                    remoteIp = context.Connection.RemoteIpAddress?.ToString();
                }

                (remoteIp, location) = await GetIpInfo(remoteIp);
                //remoteIp = await GetExternalIp();
                //location = await GetIpLocation(remoteIp);

                string deviceType = string.Empty, browser = string.Empty, os = string.Empty;
                var userAgent = context.Request.Headers["User-Agent"].FirstOrDefault();
                if (!string.IsNullOrEmpty(userAgent))
                {
                    // 解析User-Agent头
                    var parser = Parser.GetDefault();
                    var client = parser.Parse(userAgent);

                    // 提取浏览器信息
                    browser = client.UA.Family; // 浏览器名称
                    var browserVersion = client.UA.Major + "." + client.UA.Minor + "." + client.UA.Patch; // 浏览器版本
                    browser += $"({browserVersion})";

                    // 提取操作系统信息
                    os = client.OS.Family; // 操作系统名称

                    var osVersion = string.Empty; // 操作系统版本
                    if (!string.IsNullOrEmpty(client.OS.Major)) osVersion += client.OS.Major;
                    if (!string.IsNullOrEmpty(client.OS.Minor)) osVersion += "." + client.OS.Minor;
                    if (!string.IsNullOrEmpty(client.OS.Patch)) osVersion += "." + client.OS.Patch;

                    if (!string.IsNullOrEmpty(osVersion)) os += $"({osVersion})";

                    // 提取设备信息
                    deviceType = client.Device.Family; // 设备类型,如 'mobile', 'tablet', 'desktop' 等

                }

                // 记录请求结束时间
                var endTime = DateTime.UtcNow;
                // 计算耗时
                var duration = (long)(endTime - startTime).TotalMilliseconds;

                var logInfo = new Crm_TableOperationRecord()
                {
                    TableName = apiLogAttribute.TableName,
                    PortType = portType,
                    OperationItem = apiLogAttribute.OperationEnum,
                    DataId = id,
                    RequestUrl = context.Request.Path,
                    RemoteIp = remoteIp,
                    Location = location,
                    RequestParam = !string.IsNullOrEmpty(requestBodyText) ? JsonConvert.SerializeObject(requestBodyText) : null,
                    ReturnResult = !string.IsNullOrEmpty(responseBodyText) ? JsonConvert.SerializeObject(responseBodyText) : null,
                    Elapsed = duration,
                    Status = context.Response.StatusCode.ToString(),
                    CreateUserId = userId,
                    UpdatePreData = updatePreData,
                    UpdateBefData = updateBefData,
                    Browser = browser,
                    Os = os,
                    DeviceType = deviceType,
                };

                // 存储到数据库
                await _sqlSugar.Insertable(logInfo).ExecuteCommandAsync();
            }
            else
            {
                await _next(context);
            }
        }

        private async Task<string> TableInfoToJson(string tableName, int id)
        {
            if (_sqlSugar.DbMaintenance.IsAnyTable(tableName))
            {
                string jsonLabel = string.Empty;
                if (tableName.Equals("Crm_NewClientData"))
                {
                    var info = await _sqlSugar.Queryable<Crm_NewClientData>().FirstAsync(x => x.Id == id);
                    if (info != null)
                    {
                        EncryptionProcessor.DecryptProperties(info);
                        if (info != null) jsonLabel = JsonConvert.SerializeObject(info);
                    }
                }
                else
                {
                    var sql = string.Format(" Select * From {0} Where Id={1}", tableName, id);

                    var info = await _sqlSugar.SqlQueryable<dynamic>(sql).FirstAsync();
                    if (info != null) jsonLabel = JsonConvert.SerializeObject(info);
                }
                return jsonLabel;
            }

            return string.Empty;
        }

        private async Task<string> ReadRequestBody(HttpRequest request)
        {
            request.EnableBuffering();

            using var reader = new StreamReader(
                request.Body,
                Encoding.UTF8,
                detectEncodingFromByteOrderMarks: false,
                bufferSize: 8192,
                leaveOpen: true
            );

            var body = await reader.ReadToEndAsync();
            request.Body.Position = 0;
            return body;
        }

        private async Task<string> ReadResponseBody(Stream stream)
        {
            using var reader = new StreamReader(
                stream,
                Encoding.UTF8,
                detectEncodingFromByteOrderMarks: false,
                bufferSize: 8192,
                leaveOpen: true
            );

            var body = await reader.ReadToEndAsync();
            stream.Position = 0;
            return body;
        }


        private async Task<int> ReadToken(HttpContext context)
        {
            var authHeader = context.Request.Headers["Authorization"].FirstOrDefault();

            // 检查Authorization头是否存在且以"Bearer "开头
            if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
            {
                var authInfo = JwtHelper.SerializeJwt(authHeader);
                if (authInfo != null) return authInfo.UserId;
            }

            return 0;
        }
        /// <summary>
        /// 获取IP信息
        /// </summary>
        /// <param name="ip">ipv4 or ipv6</param>
        /// <returns></returns>
        private async Task<(string ip, string local)> GetIpInfo(string ip)
        {
            string local = string.Empty;

            if (IPAddress.TryParse(ip,out _))
            {
                var response = await _httpClient.GetAsync($"https://api.vore.top/api/IPdata?ip={ip}");

                response.EnsureSuccessStatusCode();
                var json = await response.Content.ReadAsStringAsync();
                var ipInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
                if (ipInfo.code == 200)
                {
                    ip = ipInfo.ipinfo.text;
                    local = $"{ipInfo.adcode.o}";
                }
            }

            return (ip, local);
        }


        private async Task<string> GetExternalIp()
        {
            var response = await _httpClient.GetAsync("https://ifconfig.me");
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }

        private async Task<string> GetIpLocation(string ip)
        {
            var response = await _httpClient.GetAsync($"https://ipinfo.io/{ip}/json?&language=zh-CN");
            response.EnsureSuccessStatusCode();
            var json = await response.Content.ReadAsStringAsync();
            var ipInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
            return $"{ipInfo.country}, {ipInfo.city}";
        }


    }
}