using Microsoft.Playwright;

namespace ScadaLink.CentralUI.PlaywrightTests;

/// <summary>
/// Verifies that navigation sections and links are shown/hidden based on the user's role.
///
/// LDAP test users (all passwords: "password"):
///   admin       → Admin only
///   designer    → Design only
///   deployer    → Deployment only
///   multi-role  → Admin + Design + Deployment
///
/// Nav structure (from NavMenu.razor):
///   All authenticated: Dashboard, Monitoring (Health Dashboard, Event Logs, Parked Messages)
///   Admin:      LDAP Mappings, Sites, Data Connections, API Keys, Audit Log
///   Design:     Templates, Shared Scripts, External Systems, Areas
///   Deployment: Instances, Deployments, Debug View
/// </summary>
[Collection("Playwright")]
public class RoleNavigationTests
{
    private readonly PlaywrightFixture _fixture;

    public RoleNavigationTests(PlaywrightFixture fixture)
    {
        _fixture = fixture;
    }

    // ── Admin-only user ─────────────────────────────────────────────

    [Fact]
    public async Task AdminUser_SeesAdminSection()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("admin", "password");

        await AssertNavLinkVisible(page, "Sites");
        await AssertNavLinkVisible(page, "Data Connections");
        await AssertNavLinkVisible(page, "API Keys");
        await AssertNavLinkVisible(page, "LDAP Mappings");
        await AssertNavLinkVisible(page, "Audit Log");
    }

    [Fact]
    public async Task AdminUser_DoesNotSeeDesignSection()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("admin", "password");

        await AssertNavLinkHidden(page, "Templates");
        await AssertNavLinkHidden(page, "Shared Scripts");
        await AssertNavLinkHidden(page, "External Systems");
    }

    [Fact]
    public async Task AdminUser_DoesNotSeeDeploymentSection()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("admin", "password");

        await AssertNavLinkHidden(page, "Instances");
        await AssertNavLinkHidden(page, "Deployments");
        await AssertNavLinkHidden(page, "Debug View");
    }

    [Fact]
    public async Task AdminUser_SeesMonitoringSection()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("admin", "password");

        await AssertNavLinkVisible(page, "Health Dashboard");
        await AssertNavLinkVisible(page, "Event Logs");
        await AssertNavLinkVisible(page, "Parked Messages");
    }

    // ── Design-only user ────────────────────────────────────────────

    [Fact]
    public async Task DesignUser_SeesDesignSection()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("designer", "password");

        await AssertNavLinkVisible(page, "Templates");
        await AssertNavLinkVisible(page, "Shared Scripts");
        await AssertNavLinkVisible(page, "External Systems");
        await AssertNavLinkVisible(page, "Areas");
    }

    [Fact]
    public async Task DesignUser_DoesNotSeeAdminSection()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("designer", "password");

        await AssertNavLinkHidden(page, "Sites");
        await AssertNavLinkHidden(page, "Data Connections");
        await AssertNavLinkHidden(page, "API Keys");
        await AssertNavLinkHidden(page, "LDAP Mappings");
        await AssertNavLinkHidden(page, "Audit Log");
    }

    [Fact]
    public async Task DesignUser_DoesNotSeeDeploymentSection()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("designer", "password");

        await AssertNavLinkHidden(page, "Instances");
        await AssertNavLinkHidden(page, "Deployments");
        await AssertNavLinkHidden(page, "Debug View");
    }

    [Fact]
    public async Task DesignUser_SeesMonitoringButNotAuditLog()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("designer", "password");

        await AssertNavLinkVisible(page, "Health Dashboard");
        await AssertNavLinkVisible(page, "Event Logs");
        await AssertNavLinkVisible(page, "Parked Messages");
        await AssertNavLinkHidden(page, "Audit Log");
    }

    // ── Deployment-only user ────────────────────────────────────────

    [Fact]
    public async Task DeploymentUser_SeesDeploymentSection()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("deployer", "password");

        await AssertNavLinkVisible(page, "Instances");
        await AssertNavLinkVisible(page, "Deployments");
        await AssertNavLinkVisible(page, "Debug View");
    }

    [Fact]
    public async Task DeploymentUser_DoesNotSeeAdminSection()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("deployer", "password");

        await AssertNavLinkHidden(page, "Sites");
        await AssertNavLinkHidden(page, "Data Connections");
        await AssertNavLinkHidden(page, "API Keys");
        await AssertNavLinkHidden(page, "LDAP Mappings");
        await AssertNavLinkHidden(page, "Audit Log");
    }

    [Fact]
    public async Task DeploymentUser_DoesNotSeeDesignSection()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("deployer", "password");

        await AssertNavLinkHidden(page, "Templates");
        await AssertNavLinkHidden(page, "Shared Scripts");
        await AssertNavLinkHidden(page, "External Systems");
    }

    [Fact]
    public async Task DeploymentUser_SeesMonitoringButNotAuditLog()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("deployer", "password");

        await AssertNavLinkVisible(page, "Health Dashboard");
        await AssertNavLinkVisible(page, "Event Logs");
        await AssertNavLinkVisible(page, "Parked Messages");
        await AssertNavLinkHidden(page, "Audit Log");
    }

    // ── Multi-role user (Admin + Design + Deployment) ───────────────

    [Fact]
    public async Task MultiRoleUser_SeesAllSections()
    {
        var page = await _fixture.NewAuthenticatedPageAsync("multi-role", "password");

        // Admin
        await AssertNavLinkVisible(page, "Sites");
        await AssertNavLinkVisible(page, "Data Connections");
        await AssertNavLinkVisible(page, "API Keys");
        await AssertNavLinkVisible(page, "LDAP Mappings");
        await AssertNavLinkVisible(page, "Audit Log");

        // Design
        await AssertNavLinkVisible(page, "Templates");
        await AssertNavLinkVisible(page, "Shared Scripts");
        await AssertNavLinkVisible(page, "External Systems");
        await AssertNavLinkVisible(page, "Areas");

        // Deployment
        await AssertNavLinkVisible(page, "Instances");
        await AssertNavLinkVisible(page, "Deployments");
        await AssertNavLinkVisible(page, "Debug View");

        // Monitoring (all authenticated)
        await AssertNavLinkVisible(page, "Health Dashboard");
        await AssertNavLinkVisible(page, "Event Logs");
        await AssertNavLinkVisible(page, "Parked Messages");
    }

    // ── All users see Dashboard ─────────────────────────────────────

    [Theory]
    [InlineData("admin")]
    [InlineData("designer")]
    [InlineData("deployer")]
    [InlineData("multi-role")]
    public async Task AllUsers_SeeDashboardLink(string username)
    {
        var page = await _fixture.NewAuthenticatedPageAsync(username, "password");

        var dashboardLink = page.GetByRole(AriaRole.Link, new() { Name = "Dashboard", Exact = true });
        await Assertions.Expect(dashboardLink).ToBeVisibleAsync();
    }

    // ── Helpers ─────────────────────────────────────────────────────

    private static async Task AssertNavLinkVisible(IPage page, string linkText)
    {
        var locator = page.Locator($"nav a:has-text('{linkText}')");
        var count = await locator.CountAsync();
        Assert.True(count > 0, $"Expected nav link '{linkText}' to be visible, but it was not found");
    }

    private static async Task AssertNavLinkHidden(IPage page, string linkText)
    {
        var locator = page.Locator($"nav a:has-text('{linkText}')");
        var count = await locator.CountAsync();
        Assert.True(count == 0, $"Expected nav link '{linkText}' to be hidden, but it was found");
    }
}
