using System.Diagnostics;
using System.Security.Claims;
using System.Text;
using System.Text.Json;
using HoneyBox.Admin.Models.OperationLog;
using HoneyBox.Admin.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace HoneyBox.Admin.Filters;

/// <summary>
/// 操作日志记录特性
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class OperationLogAttribute : Attribute, IAsyncActionFilter
{
    /// <summary>
    /// 模块名称
    /// </summary>
    public string Module { get; set; }

    /// <summary>
    /// 操作名称
    /// </summary>
    public string Action { get; set; }

    /// <summary>
    /// 是否记录请求数据
    /// </summary>
    public bool LogRequest { get; set; } = true;

    /// <summary>
    /// 是否记录响应数据
    /// </summary>
    public bool LogResponse { get; set; } = false;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="module">模块名称</param>
    /// <param name="action">操作名称</param>
    public OperationLogAttribute(string module, string action)
    {
        Module = module;
        Action = action;
    }

    /// <summary>
    /// 执行操作日志记录
    /// </summary>
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var stopwatch = Stopwatch.StartNew();
        var httpContext = context.HttpContext;
        var request = httpContext.Request;

        // 获取用户信息
        long? adminUserId = null;
        string? username = null;

        var user = httpContext.User;
        if (user?.Identity?.IsAuthenticated == true)
        {
            var userIdClaim = user.FindFirst(ClaimTypes.NameIdentifier);
            if (userIdClaim != null && long.TryParse(userIdClaim.Value, out var userId))
            {
                adminUserId = userId;
            }
            username = user.FindFirst(ClaimTypes.Name)?.Value;
        }

        // 获取请求数据
        string? requestData = null;
        if (LogRequest && context.ActionArguments.Any())
        {
            try
            {
                requestData = JsonSerializer.Serialize(context.ActionArguments, new JsonSerializerOptions
                {
                    WriteIndented = false,
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
                });

                // 限制长度
                if (requestData.Length > 4000)
                {
                    requestData = requestData.Substring(0, 4000) + "...[truncated]";
                }
            }
            catch
            {
                requestData = "[序列化失败]";
            }
        }

        // 获取IP地址
        var ip = GetClientIpAddress(httpContext);

        // 执行操作
        var executedContext = await next();
        stopwatch.Stop();

        // 获取响应数据
        string? responseData = null;
        byte status = 1;
        string? errorMsg = null;

        if (executedContext.Exception != null)
        {
            status = 0;
            errorMsg = executedContext.Exception.Message;
            if (errorMsg.Length > 500)
            {
                errorMsg = errorMsg.Substring(0, 500);
            }
        }
        else if (LogResponse && executedContext.Result is ObjectResult objectResult)
        {
            try
            {
                responseData = JsonSerializer.Serialize(objectResult.Value, new JsonSerializerOptions
                {
                    WriteIndented = false,
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
                });

                // 限制长度
                if (responseData.Length > 4000)
                {
                    responseData = responseData.Substring(0, 4000) + "...[truncated]";
                }
            }
            catch
            {
                responseData = "[序列化失败]";
            }
        }

        // 记录日志
        try
        {
            var logService = httpContext.RequestServices.GetRequiredService<IOperationLogService>();
            await logService.LogAsync(new OperationLogRequest
            {
                AdminUserId = adminUserId,
                Username = username,
                Module = Module,
                Action = Action,
                Method = request.Method,
                Url = $"{request.Path}{request.QueryString}",
                Ip = ip,
                RequestData = requestData,
                ResponseData = responseData,
                Status = status,
                ErrorMsg = errorMsg,
                Duration = (int)stopwatch.ElapsedMilliseconds
            });
        }
        catch (Exception ex)
        {
            // 日志记录失败不影响主流程
            var logger = httpContext.RequestServices.GetRequiredService<ILogger<OperationLogAttribute>>();
            logger.LogError(ex, "记录操作日志失败");
        }
    }

    /// <summary>
    /// 获取客户端IP地址
    /// </summary>
    private static string GetClientIpAddress(HttpContext httpContext)
    {
        // 优先从 X-Forwarded-For 获取（反向代理场景）
        var forwardedFor = httpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
        if (!string.IsNullOrEmpty(forwardedFor))
        {
            return forwardedFor.Split(',')[0].Trim();
        }

        // 从 X-Real-IP 获取
        var realIp = httpContext.Request.Headers["X-Real-IP"].FirstOrDefault();
        if (!string.IsNullOrEmpty(realIp))
        {
            return realIp;
        }

        // 从连接获取
        return httpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
    }
}
