using FluentAssertions;
using foodmarket.Domain.Organizations;
using foodmarket.UnitTests.Support;
using Microsoft.EntityFrameworkCore;
using Xunit;

namespace foodmarket.UnitTests;

/// <summary>Мультитенантный query-filter AppDbContext: tenant видит только свои
/// строки; SuperAdmin без override — все; SuperAdmin в режиме «открыть как…»
/// (override) снова ограничен выбранной оргой. EmployeeRole выбран как
/// TenantEntity без внешних FK — минимальный засев.</summary>
public class TenantQueryFilterTests
{
    private static readonly Guid OrgA = Guid.NewGuid();
    private static readonly Guid OrgB = Guid.NewGuid();

    private static EmployeeRole Role(Guid org, string name) =>
        new() { OrganizationId = org, Name = name, Permissions = new RolePermissions() };

    private static async Task SeedTwoOrgsAsync(SqliteDb sqlite)
    {
        using var seed = sqlite.Create(new FakeTenantContext { IsSuperAdmin = true });
        seed.EmployeeRoles.AddRange(Role(OrgA, "A-role"), Role(OrgB, "B-role"));
        await seed.SaveChangesAsync();
    }

    [Fact]
    public async Task Tenant_sees_only_its_own_rows()
    {
        using var sqlite = new SqliteDb();
        await SeedTwoOrgsAsync(sqlite);

        using var db = sqlite.Create(new FakeTenantContext { OrganizationId = OrgA });
        var roles = await db.EmployeeRoles.ToListAsync();

        roles.Should().ContainSingle()
            .Which.OrganizationId.Should().Be(OrgA);
    }

    [Fact]
    public async Task Other_tenant_cannot_see_foreign_rows()
    {
        using var sqlite = new SqliteDb();
        await SeedTwoOrgsAsync(sqlite);

        using var db = sqlite.Create(new FakeTenantContext { OrganizationId = OrgB });
        var roles = await db.EmployeeRoles.ToListAsync();

        roles.Should().OnlyContain(r => r.OrganizationId == OrgB);
        roles.Should().HaveCount(1);
    }

    [Fact]
    public async Task SuperAdmin_without_override_sees_all_tenants()
    {
        using var sqlite = new SqliteDb();
        await SeedTwoOrgsAsync(sqlite);

        using var db = sqlite.Create(new FakeTenantContext { IsSuperAdmin = true });
        (await db.EmployeeRoles.CountAsync()).Should().Be(2);
    }

    [Fact]
    public async Task SuperAdmin_with_override_is_scoped_to_selected_org()
    {
        using var sqlite = new SqliteDb();
        await SeedTwoOrgsAsync(sqlite);

        // «Открыть как…» орг A — изоляция обязана работать даже для SuperAdmin.
        using var db = sqlite.Create(new FakeTenantContext
        {
            IsSuperAdmin = true,
            IsTenantOverride = true,
            OrganizationId = OrgA,
        });
        var roles = await db.EmployeeRoles.ToListAsync();

        roles.Should().ContainSingle().Which.OrganizationId.Should().Be(OrgA);
    }
}
