namespace GmRelay.Bot.Tests.Web;

public sealed class PortfolioPagesTests
{
    [Fact]
    public async Task PortfolioEditorPage_ShouldBeAuthorizedAndExposeEditorActions()
    {
        var editor = await ReadRepositoryFileAsync("src/GmRelay.Web/Components/Pages/PortfolioEditor.razor");

        Assert.Contains("@page \"/portfolio/manage/{PortfolioGameId:guid}\"", editor, StringComparison.Ordinal);
        Assert.Contains("@attribute [Authorize]", editor, StringComparison.Ordinal);
        Assert.Contains("InputFile", editor, StringComparison.Ordinal);
        Assert.Contains("ReplaceCoverForCurrentUserAsync", editor, StringComparison.Ordinal);
        Assert.Contains("SetPublicationForCurrentUserAsync", editor, StringComparison.Ordinal);
        Assert.Contains("ModerateReviewForCurrentUserAsync", editor, StringComparison.Ordinal);
    }

    [Fact]
    public async Task GroupDetailsPage_ShouldExposePortfolioManagementActions()
    {
        var groupDetails = await ReadRepositoryFileAsync("src/GmRelay.Web/Components/Pages/GroupDetails.razor");

        Assert.Contains("CreateDraftForCurrentUserAsync", groupDetails, StringComparison.Ordinal);
    }

    [Fact]
    public async Task GroupCompletedSessionsPage_ShouldBeAuthorizedAndExposeCompletedSessions()
    {
        var completedSessions = await ReadRepositoryFileAsync("src/GmRelay.Web/Components/Pages/GroupCompletedSessions.razor");

        Assert.Contains("@page \"/group/{GroupId:guid}/completed\"", completedSessions, StringComparison.Ordinal);
        Assert.Contains("@attribute [Authorize]", completedSessions, StringComparison.Ordinal);
        Assert.Contains("GetCompletedSessionsForCurrentUserAsync", completedSessions, StringComparison.Ordinal);
        Assert.Contains("CreateDraftForCurrentUserAsync", completedSessions, StringComparison.Ordinal);
    }

    [Fact]
    public async Task SessionHistoryPage_ShouldExposeQuickPortfolioActionForPastSessions()
    {
        var sessionHistory = await ReadRepositoryFileAsync("src/GmRelay.Web/Components/Pages/SessionHistory.razor");

        Assert.Contains("CreateDraftForCurrentUserAsync", sessionHistory, StringComparison.Ordinal);
        Assert.Contains("Добавить в портфолио", sessionHistory, StringComparison.Ordinal);
    }

    [Fact]
    public async Task AppCss_ShouldStylePortfolioManagementComponents()
    {
        var css = await ReadRepositoryFileAsync("src/GmRelay.Web/wwwroot/app.css");

        Assert.Contains(".portfolio-management-list", css, StringComparison.Ordinal);
        Assert.Contains(".portfolio-editor-grid", css, StringComparison.Ordinal);
        Assert.Contains(".portfolio-option-list", css, StringComparison.Ordinal);
        Assert.Contains(".portfolio-review-moderation", css, StringComparison.Ordinal);
    }

    [Fact]
    public async Task PublicPortfolioPage_ShouldExposeSanitizedDetailAndReviewForm()
    {
        var publicPortfolio = await ReadRepositoryFileAsync("src/GmRelay.Web/Components/Pages/PublicPortfolio.razor");

        Assert.Contains("@page \"/portfolio/{Slug}\"", publicPortfolio, StringComparison.Ordinal);
        Assert.Contains("@layout PublicLayout", publicPortfolio, StringComparison.Ordinal);
        Assert.DoesNotContain("@attribute [Authorize]", publicPortfolio, StringComparison.Ordinal);
        Assert.Contains("GetPublicPortfolioGameBySlugAsync", publicPortfolio, StringComparison.Ordinal);
        Assert.Contains("SubmitReviewForCurrentUserAsync", publicPortfolio, StringComparison.Ordinal);
        Assert.Contains("publicationConsent", publicPortfolio, StringComparison.Ordinal);
        Assert.DoesNotContain("PlayerId", publicPortfolio, StringComparison.Ordinal);
        Assert.DoesNotContain("StorageKey", publicPortfolio, StringComparison.Ordinal);
    }

    [Fact]
    public async Task PublicMasterProfilePage_ShouldIncludePortfolioCardGrid()
    {
        var publicMaster = await ReadRepositoryFileAsync("src/GmRelay.Web/Components/Pages/PublicMasterProfile.razor");

        Assert.Contains("PortfolioCardGrid", publicMaster, StringComparison.Ordinal);
        Assert.Contains("GetPublicPortfolioGamesForMasterAsync", publicMaster, StringComparison.Ordinal);
    }

    [Fact]
    public async Task PublicClubPage_ShouldIncludePortfolioCardGrid()
    {
        var publicClub = await ReadRepositoryFileAsync("src/GmRelay.Web/Components/Pages/PublicClub.razor");

        Assert.Contains("PortfolioCardGrid", publicClub, StringComparison.Ordinal);
        Assert.Contains("GetPublicPortfolioGamesForClubAsync", publicClub, StringComparison.Ordinal);
    }

    [Fact]
    public async Task AppCss_ShouldStylePublicPortfolioComponents()
    {
        var css = await ReadRepositoryFileAsync("src/GmRelay.Web/wwwroot/app.css");

        Assert.Contains(".portfolio-grid", css, StringComparison.Ordinal);
        Assert.Contains(".portfolio-card", css, StringComparison.Ordinal);
        Assert.Contains(".portfolio-card-cover", css, StringComparison.Ordinal);
        Assert.Contains(".portfolio-cover-hero", css, StringComparison.Ordinal);
        Assert.Contains(".portfolio-review-list", css, StringComparison.Ordinal);
        Assert.Contains(".portfolio-review-card", css, StringComparison.Ordinal);
    }

    private static async Task<string> ReadRepositoryFileAsync(string relativePath)
    {
        var directory = new DirectoryInfo(AppContext.BaseDirectory);
        while (directory is not null)
        {
            var candidate = Path.Combine(directory.FullName, relativePath);
            if (File.Exists(candidate))
            {
                return await File.ReadAllTextAsync(candidate);
            }

            directory = directory.Parent;
        }

        throw new FileNotFoundException($"Could not locate repository file '{relativePath}'.");
    }
}
