using System.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using ColaFlow.Modules.ProjectManagement.Domain.Aggregates.ProjectAggregate;
using ColaFlow.Modules.ProjectManagement.Domain.Entities;
using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;

namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence;

/// <summary>
/// Project Management Module DbContext
/// </summary>
public class PMDbContext : DbContext
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public PMDbContext(DbContextOptions<PMDbContext> options, IHttpContextAccessor httpContextAccessor)
        : base(options)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public DbSet<Project> Projects => Set<Project>();
    public DbSet<Epic> Epics => Set<Epic>();
    public DbSet<Story> Stories => Set<Story>();
    public DbSet<WorkTask> Tasks => Set<WorkTask>();
    public DbSet<AuditLog> AuditLogs => Set<AuditLog>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Set default schema for this module (must be before configurations)
        modelBuilder.HasDefaultSchema("project_management");

        // Apply all entity configurations from this assembly
        modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());

        // Multi-tenant Global Query Filters
        modelBuilder.Entity<Project>().HasQueryFilter(p =>
            p.TenantId == GetCurrentTenantId());

        modelBuilder.Entity<Epic>().HasQueryFilter(e =>
            e.TenantId == GetCurrentTenantId());

        modelBuilder.Entity<Story>().HasQueryFilter(s =>
            s.TenantId == GetCurrentTenantId());

        modelBuilder.Entity<WorkTask>().HasQueryFilter(t =>
            t.TenantId == GetCurrentTenantId());

        modelBuilder.Entity<AuditLog>().HasQueryFilter(a =>
            a.TenantId == GetCurrentTenantId());
    }

    private TenantId GetCurrentTenantId()
    {
        var tenantIdClaim = _httpContextAccessor?.HttpContext?.User
            .FindFirst("tenant_id")?.Value;

        if (Guid.TryParse(tenantIdClaim, out var tenantId) && tenantId != Guid.Empty)
        {
            return TenantId.From(tenantId);
        }

        // Return a dummy value for queries outside HTTP context (e.g., migrations)
        // These will return no results due to the filter
        return TenantId.From(Guid.Empty);
    }
}
