using EonaCat.LogStack.Core;
using System;
using System.Runtime.CompilerServices;

// This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/License for full license details.

namespace EonaCat.LogStack.Boosters
{
    /// <summary>
    /// Booster that extracts context from HTTP requests.
    /// Requires IHttpContextAccessor to be registered in DI.
    /// </summary>
    public sealed class RequestContextBooster : BoosterBase
    {
        private readonly object? _httpContextAccessor;

        public RequestContextBooster(object? httpContextAccessor = null) : base("RequestContext")
        {
            _httpContextAccessor = httpContextAccessor;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override bool Boost(ref LogEventBuilder builder)
        {
            try
            {
                var httpContext = GetHttpContext();
                if (httpContext == null)
                {
                    return true;
                }

                var request = GetRequest(httpContext);
                if (request == null)
                {
                    return true;
                }

                // Add HTTP method
                var method = GetRequestMethod(request);
                if (!string.IsNullOrEmpty(method))
                {
                    builder.WithProperty("HttpMethod", method);
                }

                // Add request path
                var path = GetRequestPath(request);
                if (!string.IsNullOrEmpty(path))
                {
                    builder.WithProperty("RequestPath", path);
                }

                // Add request host
                var host = GetRequestHost(request);
                if (!string.IsNullOrEmpty(host))
                {
                    builder.WithProperty("RequestHost", host);
                }

                // Add user if available
                var user = GetUser(httpContext);
                if (!string.IsNullOrEmpty(user))
                {
                    builder.WithProperty("User", user);
                }

                // Add trace identifier
                var traceId = GetTraceId(httpContext);
                if (!string.IsNullOrEmpty(traceId))
                {
                    builder.WithProperty("TraceId", traceId);
                }
            }
            catch
            {
                // Silently fail - don't let booster errors crash logging
            }
            return true;
        }

        private object? GetHttpContext()
        {
            try
            {
                if (_httpContextAccessor == null)
                {
                    return null;
                }

                var prop = _httpContextAccessor.GetType().GetProperty("HttpContext");
                return prop?.GetValue(_httpContextAccessor);
            }
            catch
            {
                return null;
            }
        }

        private object? GetRequest(object httpContext)
        {
            try
            {
                var prop = httpContext.GetType().GetProperty("Request");
                return prop?.GetValue(httpContext);
            }
            catch
            {
                return null;
            }
        }

        private string? GetRequestMethod(object request)
        {
            try
            {
                var prop = request.GetType().GetProperty("Method");
                return prop?.GetValue(request)?.ToString();
            }
            catch
            {
                return null;
            }
        }

        private string? GetRequestPath(object request)
        {
            try
            {
                var prop = request.GetType().GetProperty("Path");
                return prop?.GetValue(request)?.ToString();
            }
            catch
            {
                return null;
            }
        }

        private string? GetRequestHost(object request)
        {
            try
            {
                var prop = request.GetType().GetProperty("Host");
                return prop?.GetValue(request)?.ToString();
            }
            catch
            {
                return null;
            }
        }

        private string? GetUser(object httpContext)
        {
            try
            {
                var prop = httpContext.GetType().GetProperty("User");
                var user = prop?.GetValue(httpContext);
                if (user == null)
                {
                    return null;
                }

                var identityProp = user.GetType().GetProperty("Identity");
                var identity = identityProp?.GetValue(user);
                if (identity == null)
                {
                    return null;
                }

                var nameProp = identity.GetType().GetProperty("Name");
                return nameProp?.GetValue(identity)?.ToString();
            }
            catch
            {
                return null;
            }
        }

        private string? GetTraceId(object httpContext)
        {
            try
            {
                var prop = httpContext.GetType().GetProperty("TraceIdentifier");
                return prop?.GetValue(httpContext)?.ToString();
            }
            catch
            {
                return null;
            }
        }
    }
}
