using Microsoft.Playwright;

namespace ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests;

[Collection("Playwright")]
public class NavigationTests
{
    private readonly PlaywrightFixture _fixture;

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

    [Fact]
    public async Task Dashboard_IsVisibleAfterLogin()
    {
        var page = await _fixture.NewAuthenticatedPageAsync();

        // The nav sidebar should be visible with the brand. ToContainText, not
        // ToHaveText: the brand also carries the accent mark glyph (▮).
        await Expect(page.Locator(".brand")).ToContainTextAsync("ScadaBridge");
        // The nav should contain "Dashboard" link (exact match to avoid "Health Dashboard")
        await Expect(page.GetByRole(AriaRole.Link, new() { Name = "Dashboard", Exact = true })).ToBeVisibleAsync();
    }

    [Theory]
    [InlineData("Sites", "/admin/sites")]
    [InlineData("API Keys", "/admin/api-keys")]
    [InlineData("LDAP Mappings", "/admin/ldap-mappings")]
    public async Task AdminNavLinks_NavigateCorrectly(string linkText, string expectedPath)
    {
        var page = await _fixture.NewAuthenticatedPageAsync();
        await ClickNavAndWait(page, linkText, expectedPath);
    }

    [Theory]
    [InlineData("SMTP Configuration", "/notifications/smtp")]
    [InlineData("Notification Lists", "/notifications/lists")]
    [InlineData("Notification Report", "/notifications/report")]
    [InlineData("Notification KPIs", "/notifications/kpis")]
    public async Task NotificationsNavLinks_NavigateCorrectly(string linkText, string expectedPath)
    {
        var page = await _fixture.NewAuthenticatedPageAsync();
        await ClickNavAndWait(page, linkText, expectedPath);
    }

    [Theory]
    [InlineData("Templates", "/design/templates")]
    [InlineData("Shared Scripts", "/design/shared-scripts")]
    [InlineData("Connections", "/design/connections")]
    [InlineData("External Systems", "/design/external-systems")]
    public async Task DesignNavLinks_NavigateCorrectly(string linkText, string expectedPath)
    {
        var page = await _fixture.NewAuthenticatedPageAsync();
        await ClickNavAndWait(page, linkText, expectedPath);
    }

    [Theory]
    [InlineData("Topology", "/deployment/topology")]
    [InlineData("Deployments", "/deployment/deployments")]
    public async Task DeploymentNavLinks_NavigateCorrectly(string linkText, string expectedPath)
    {
        var page = await _fixture.NewAuthenticatedPageAsync();
        await ClickNavAndWait(page, linkText, expectedPath);
    }

    [Theory]
    [InlineData("Health Dashboard", "/monitoring/health")]
    [InlineData("Event Logs", "/monitoring/event-logs")]
    [InlineData("Parked Messages", "/monitoring/parked-messages")]
    public async Task MonitoringNavLinks_NavigateCorrectly(string linkText, string expectedPath)
    {
        var page = await _fixture.NewAuthenticatedPageAsync();
        await ClickNavAndWait(page, linkText, expectedPath);
    }

    // Maps each navigable route to the exact heading text rendered by that page.
    private static readonly Dictionary<string, string> RouteHeadings = new()
    {
        ["/admin/sites"]                = "Site Management",
        ["/admin/api-keys"]             = "API Key Management",
        ["/admin/ldap-mappings"]        = "LDAP Group Mappings",
        ["/notifications/smtp"]         = "SMTP Configuration",
        ["/notifications/lists"]        = "Notification Lists",
        ["/notifications/report"]       = "Notification Report",
        ["/notifications/kpis"]         = "Notification KPIs",
        ["/design/templates"]           = "Templates",
        ["/design/shared-scripts"]      = "Shared Scripts",
        ["/design/connections"]         = "Connections",
        ["/design/external-systems"]    = "Integration Definitions",
        ["/deployment/topology"]        = "Topology",
        ["/deployment/deployments"]     = "Deployment Status",
        ["/monitoring/health"]          = "Health Dashboard",
        ["/monitoring/event-logs"]      = "Site Event Logs",
        ["/monitoring/parked-messages"] = "Parked Messages",
    };

    private static async Task ClickNavAndWait(IPage page, string linkText, string expectedPath)
    {
        // Sections are collapsed by default — open them so the link is in the DOM.
        await PlaywrightFixture.ExpandAllNavSectionsAsync(page);
        await page.Locator($"nav a:has-text('{linkText}')").ClickAsync();
        await PlaywrightFixture.WaitForPathAsync(page, expectedPath);
        Assert.Contains(expectedPath, page.Url);

        // Verify the destination page actually rendered its heading (catches 500s
        // and blank renders that a URL-only check would miss).
        // Every mapped route renders its heading as an <h4> — tightened from the
        // broader "h1, h4, h5" to prevent strict-mode violations if multiple
        // heading elements match.
        var expectedHeading = RouteHeadings[expectedPath];
        await Assertions.Expect(page.Locator("h4", new() { HasText = expectedHeading })).ToBeVisibleAsync();
    }

    private static ILocatorAssertions Expect(ILocator locator) =>
        Assertions.Expect(locator);
}
