using System.Security.Claims;
using foodmarket.Application.Common.Tenancy;

namespace foodmarket.Api.Infrastructure.Tenancy;

public class HttpContextTenantContext : ITenantContext
{
    public const string OrganizationClaim = "org_id";
    public const string SuperAdminRole = "SuperAdmin";
    /// <summary>HTTP-заголовок переключения tenant'а для SuperAdmin'а: «открыть как…»
    /// конкретную организацию. Без этого header'а супер-админ не привязан к
    /// конкретной орге (видит всё через query-filter bypass).</summary>
    public const string OrgOverrideHeader = "X-Org-Override";
    /// <summary>HTTP-заголовок включения edit-mode в режиме «открыть как…»:
    /// клиент шлёт reason (≥10 символов), сервер разрешает мутации и пишет
    /// каждую запись в SuperAdminAuditLog с этой причиной. Срок действия
    /// токена ограничен 30 минутами на стороне фронта (после — UI отключает).</summary>
    public const string EditReasonHeader = "X-Org-Override-Reason";

    // Override для background задач (например, импорт из MoySklad): сохраняем tenant
    // в AsyncLocal на время выполнения фонового Task. HttpContext там отсутствует,
    // но query-filter'у по-прежнему нужен orgId — вот его и берём из override.
    private static readonly AsyncLocal<(Guid? OrgId, bool IsSuper)?> _override = new();

    public static IDisposable UseOverride(Guid orgId, bool isSuperAdmin = false)
    {
        _override.Value = (orgId, isSuperAdmin);
        return new OverrideScope();
    }

    private sealed class OverrideScope : IDisposable
    {
        public void Dispose() => _override.Value = null;
    }

    private readonly IHttpContextAccessor _accessor;

    public HttpContextTenantContext(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }

    public bool IsAuthenticated
    {
        get
        {
            if (_override.Value is not null) return true;
            return _accessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false;
        }
    }

    public bool IsSuperAdmin
    {
        get
        {
            if (_override.Value is { IsSuper: var s }) return s;
            return _accessor.HttpContext?.User?.IsInRole(SuperAdminRole) ?? false;
        }
    }

    public Guid? OrganizationId
    {
        get
        {
            if (_override.Value is { OrgId: var o }) return o;
            if (TryGetHttpOverrideOrg(out var http)) return http;
            var claim = _accessor.HttpContext?.User?.FindFirst(OrganizationClaim)?.Value;
            return Guid.TryParse(claim, out var id) ? id : null;
        }
    }

    public bool IsTenantOverride
    {
        get
        {
            // AsyncLocal-override (background tasks) не считаем «открыть как…» —
            // он используется в импорте/Hangfire, где и так применяется фильтр
            // (IsSuper=false по умолчанию). Override-режим — только HTTP-header.
            return TryGetHttpOverrideOrg(out _);
        }
    }

    private bool TryGetHttpOverrideOrg(out Guid orgId)
    {
        orgId = Guid.Empty;
        var ctx = _accessor.HttpContext;
        if (ctx is null) return false;
        if (ctx.User?.IsInRole(SuperAdminRole) != true) return false;
        if (!ctx.Request.Headers.TryGetValue(OrgOverrideHeader, out var headerVal)) return false;
        return Guid.TryParse(headerVal.ToString(), out orgId);
    }
}
