@page "/portfolio/{Slug}"
@layout PublicLayout
@inject IPortfolioStore PortfolioStore
@inject AuthorizedPortfolioService AuthorizedPortfolio
@inject NavigationManager Navigation
@inject AuthenticationStateProvider AuthStateProvider
@using GmRelay.Shared.Domain
@using GmRelay.Web.Services.Portfolio

<PageTitle>@PageTitleText</PageTitle>

@if (loaded && game is null)
{
    <HeadContent>
        <meta name="robots" content="noindex, nofollow" />
    </HeadContent>

    <section class="public-hero public-hero-compact">
        <span class="status-badge status-neutral">Недоступно</span>
        <h1>Портфолио не найдено</h1>
        <p>Эта игра скрыта, ещё не опубликована или короткий адрес больше не используется.</p>
    </section>
}
else if (!loaded)
{
    <section class="public-hero public-hero-compact">
        <div class="skeleton skeleton-text" style="width: 55%; height: 2rem;"></div>
        <div class="skeleton skeleton-text" style="width: 75%;"></div>
    </section>
}
else if (game is not null)
{
    <HeadContent>
        <meta name="description" content="@($"Портфолио {game.Title} — завершённая игра в GM-Relay.")" />
    </HeadContent>

    @if (!string.IsNullOrWhiteSpace(game.CoverPath))
    {
        <div class="portfolio-cover-hero" style="background-image: url('@game.CoverPath')"></div>
    }

    <section class="public-hero public-hero-compact">
        <span class="status-badge status-success">Завершено</span>
        <h1>@game.Title</h1>
        <p>Завершено @game.CompletedAt.ToLocalTime().FormatMoscow()</p>
        <div class="session-badges">
            @if (!string.IsNullOrWhiteSpace(game.System))
            {
                <span class="status-badge status-info">@GetSystemDisplayName(game.System)</span>
            }
            @if (!string.IsNullOrWhiteSpace(game.Format))
            {
                <span class="status-badge status-neutral">@TranslateFormat(game.Format)</span>
            }
        </div>
    </section>

    <article class="glass-card public-session-detail">
        @if (!string.IsNullOrWhiteSpace(game.Description))
        {
            <div class="session-description">
                <h3>Описание</h3>
                <p>@game.Description</p>
            </div>
        }

        @if (game.Masters.Count > 0)
        {
            <div class="public-master-link">
                <span>Мастера</span>
                @foreach (var master in game.Masters)
                {
                    <a href="@($"/gm/{master.Slug}")">@master.DisplayName</a>
                }
            </div>
        }

        @if (!string.IsNullOrWhiteSpace(game.ClubSlug) && !string.IsNullOrWhiteSpace(game.ClubName))
        {
            <div class="public-master-link">
                <span>Клуб</span>
                <a href="@($"/club/{game.ClubSlug}")">@game.ClubName</a>
            </div>
        }

        <div class="public-settings-actions">
            <a class="btn-gm btn-gm-outline" href="@PublicPortfolioUrl" target="_blank" rel="noopener noreferrer">Ссылка на портфолио</a>
        </div>
    </article>

    <section class="glass-card portfolio-section">
        <h2>Отзывы игроков</h2>
        @if (game.Reviews.Count == 0)
        {
            <p>Пока нет одобренных отзывов.</p>
        }
        else
        {
            <ul class="portfolio-review-list">
                @foreach (var review in game.Reviews)
                {
                    <li class="portfolio-review-card">
                        <div class="portfolio-review-meta">
                            <span class="portfolio-review-author">@review.AuthorDisplayName</span>
                            <span class="portfolio-review-date">@review.CreatedAt.ToLocalTime().FormatMoscowShort()</span>
                        </div>
                        <p class="portfolio-review-body">@review.Body</p>
                    </li>
                }
            </ul>
        }
    </section>

    <section class="glass-card portfolio-section">
        <h2>Оставить отзыв</h2>
        @switch (submissionState)
        {
            case PortfolioReviewSubmissionState.RequiresAuthentication:
                <p>Войдите, чтобы оставить отзыв об этом приключении.</p>
                <div class="public-settings-actions">
                    <a class="btn-gm btn-gm-primary" href="@GetLoginUrl()">Войти</a>
                </div>
                break;
            case PortfolioReviewSubmissionState.Ineligible:
                <p>Отзыв могут оставить только игроки, участвовавшие в этом приключении.</p>
                break;
            case PortfolioReviewSubmissionState.AlreadySubmitted:
                <p>Отзыв отправлен на модерацию.</p>
                break;
            case PortfolioReviewSubmissionState.Eligible:
                <EditForm Model="reviewModel" OnValidSubmit="SubmitReviewAsync" FormName="portfolio-review">
                    <div class="portfolio-editor-fields">
                        <label>
                            <span>Текст отзыва</span>
                            <textarea class="portfolio-review-textarea"
                                      @bind="reviewModel.Body"
                                      @bind:event="oninput"
                                      maxlength="2000"
                                      minlength="10"
                                      rows="5"
                                      placeholder="Что вам запомнилось в этой игре?"
                                      required></textarea>
                        </label>
                        <label class="portfolio-review-consent">
                            <input type="checkbox"
                                   name="publicationConsent"
                                   @bind="reviewModel.PublicationConsent"
                                   required />
                            <span>Я даю согласие на публикацию этого отзыва</span>
                        </label>
                        @if (!string.IsNullOrWhiteSpace(submissionError))
                        {
                            <p class="portfolio-review-error">@submissionError</p>
                        }
                        <div class="public-settings-actions">
                            <button type="submit" class="btn-gm btn-gm-primary" disabled="@isSubmitting">
                                @(isSubmitting ? "Отправка..." : "Отправить отзыв")
                            </button>
                        </div>
                    </div>
                </EditForm>
                break;
        }
    </section>
}

@code {
    [Parameter] public string? Slug { get; set; }

    private PublicPortfolioGame? game;
    private PortfolioReviewSubmissionState submissionState = PortfolioReviewSubmissionState.RequiresAuthentication;
    private ReviewFormModel reviewModel = new();
    private string? submissionError;
    private bool isSubmitting;
    private bool loaded;

    private string PageTitleText => game is null ? "Портфолио — GM-Relay" : $"{game.Title} — GM-Relay";

    private string PublicPortfolioUrl => Navigation.ToAbsoluteUri($"/portfolio/{Slug}").ToString();

    private string GetLoginUrl() => $"/login?returnUrl={Uri.EscapeDataString($"/portfolio/{Slug}")}";

    protected override async Task OnParametersSetAsync()
    {
        loaded = false;
        var trimmedSlug = string.IsNullOrWhiteSpace(Slug) ? null : Slug.Trim();
        game = trimmedSlug is null
            ? null
            : await PortfolioStore.GetPublicPortfolioGameBySlugAsync(trimmedSlug);

        if (game is not null)
        {
            submissionState = await AuthorizedPortfolio.GetReviewSubmissionStateForCurrentUserAsync(game.Slug);
        }

        reviewModel = new ReviewFormModel();
        submissionError = null;
        isSubmitting = false;
        loaded = true;
    }

    private async Task SubmitReviewAsync()
    {
        if (game is null)
        {
            return;
        }

        if (!reviewModel.PublicationConsent)
        {
            submissionError = "Нужно подтвердить согласие на публикацию.";
            return;
        }

        if (string.IsNullOrWhiteSpace(reviewModel.Body) || reviewModel.Body.Trim().Length < 10)
        {
            submissionError = "Отзыв должен содержать не меньше 10 символов.";
            return;
        }

        isSubmitting = true;
        submissionError = null;
        try
        {
            await AuthorizedPortfolio.SubmitReviewForCurrentUserAsync(
                game.Slug,
                reviewModel.Body,
                reviewModel.PublicationConsent);
            submissionState = PortfolioReviewSubmissionState.AlreadySubmitted;
            reviewModel = new ReviewFormModel();
        }
        catch (Exception ex)
        {
            submissionError = ex.Message;
        }
        finally
        {
            isSubmitting = false;
        }
    }

    private static string GetSystemDisplayName(string? system)
    {
        if (string.IsNullOrWhiteSpace(system))
            return system ?? string.Empty;

        if (Enum.TryParse<GameSystem>(system, out var gs))
            return gs.ToDisplayName();

        return system;
    }

    private static string TranslateFormat(string format) => format switch
    {
        "Online" => "Онлайн",
        "Offline" => "Офлайн",
        "Hybrid" => "Гибрид",
        _ => format
    };

    private sealed class ReviewFormModel
    {
        public string Body { get; set; } = string.Empty;
        public bool PublicationConsent { get; set; }
    }
}
