@page "/showcase"
@layout PublicLayout
@inject ISessionStore SessionStore
@inject NavigationManager Navigation
@using GmRelay.Shared.Features.Showcase

<PageTitle>Каталог игр — GM-Relay</PageTitle>

<HeadContent>
    <meta name="description" content="Каталог настольных ролевых игр GM-Relay. Найдите игру по душе — ваншоты, кампании, онлайн и офлайн." />
</HeadContent>

<section class="public-hero">
    <h1>Каталог игр</h1>
    <p>Найдите настольную ролевую игру по душе — ваншоты, кампании, онлайн и офлайн.</p>
</section>

<section class="glass-card showcase-filters">
    <div class="showcase-filter-group">
        <span class="showcase-filter-label">Когда</span>
        <div class="showcase-filter-buttons">
            <button class="btn-gm @(filter.Date == DateFilter.Today ? "btn-gm-primary" : "btn-gm-outline")" @onclick="() => SetDate(DateFilter.Today)">Сегодня</button>
            <button class="btn-gm @(filter.Date == DateFilter.Tomorrow ? "btn-gm-primary" : "btn-gm-outline")" @onclick="() => SetDate(DateFilter.Tomorrow)">Завтра</button>
            <button class="btn-gm @(filter.Date == DateFilter.ThisWeek ? "btn-gm-primary" : "btn-gm-outline")" @onclick="() => SetDate(DateFilter.ThisWeek)">На этой неделе</button>
            <button class="btn-gm @(filter.Date == DateFilter.All ? "btn-gm-primary" : "btn-gm-outline")" @onclick="() => SetDate(DateFilter.All)">Все</button>
        </div>
    </div>

    <div class="showcase-filter-group">
        <span class="showcase-filter-label">Места</span>
        <div class="showcase-filter-buttons">
            <button class="btn-gm @(filter.Seats == SeatFilter.Available ? "btn-gm-primary" : "btn-gm-outline")" @onclick="() => SetSeats(SeatFilter.Available)">Есть места</button>
            <button class="btn-gm @(filter.Seats == SeatFilter.Waitlist ? "btn-gm-primary" : "btn-gm-outline")" @onclick="() => SetSeats(SeatFilter.Waitlist)">Лист ожидания</button>
            <button class="btn-gm @(filter.Seats == SeatFilter.Any ? "btn-gm-primary" : "btn-gm-outline")" @onclick="() => SetSeats(SeatFilter.Any)">Любые</button>
        </div>
    </div>

    <div class="showcase-filter-group">
        <label class="showcase-filter-label" for="system-filter">Система</label>
        <select id="system-filter" class="gm-form-control showcase-filter-select" aria-label="Система" @onchange="OnSystemChanged">
            <option value="" selected="@(filter.System is null)">Любая</option>
            @foreach (var system in Enum.GetValues<GameSystem>())
            {
                var name = system.ToString();
                <option value="@name" selected="@(filter.System == name)">@system.ToDisplayName()</option>
            }
        </select>
    </div>

    <div class="showcase-filter-group">
        <span class="showcase-filter-label">Тип</span>
        <div class="showcase-filter-buttons">
            <button class="btn-gm @(filter.IsOneShot == true ? "btn-gm-primary" : "btn-gm-outline")" @onclick="() => SetOneShot(true)">Ваншот</button>
            <button class="btn-gm @(filter.IsOneShot == false ? "btn-gm-primary" : "btn-gm-outline")" @onclick="() => SetOneShot(false)">Кампания</button>
            <button class="btn-gm @(filter.IsOneShot is null ? "btn-gm-primary" : "btn-gm-outline")" @onclick="() => SetOneShot(null)">Любое</button>
        </div>
    </div>

    <div class="showcase-filter-group">
        <span class="showcase-filter-label">Формат</span>
        <div class="showcase-filter-buttons">
            <button class="btn-gm @(filter.Format == "Online" ? "btn-gm-primary" : "btn-gm-outline")" @onclick="@(() => SetFormat("Online"))">Онлайн</button>
            <button class="btn-gm @(filter.Format == "Offline" ? "btn-gm-primary" : "btn-gm-outline")" @onclick="@(() => SetFormat("Offline"))">Офлайн</button>
            <button class="btn-gm @(filter.Format == "Hybrid" ? "btn-gm-primary" : "btn-gm-outline")" @onclick="@(() => SetFormat("Hybrid"))">Гибрид</button>
            <button class="btn-gm @(filter.Format is null ? "btn-gm-primary" : "btn-gm-outline")" @onclick="@(() => SetFormat((string?)null))">Любой</button>
        </div>
    </div>
</section>

@if (loading && sessions.Count == 0)
{
    <div class="showcase-grid">
        @for (var i = 0; i < 6; i++)
        {
            <div class="glass-card showcase-card showcase-skeleton">
                <div class="skeleton showcase-skeleton-image"></div>
                <div class="showcase-card-body">
                    <div class="skeleton skeleton-text" style="width: 70%;"></div>
                    <div class="skeleton skeleton-text" style="width: 45%;"></div>
                    <div class="skeleton skeleton-text" style="width: 55%;"></div>
                </div>
            </div>
        }
    </div>
}
else if (!loading && sessions.Count == 0)
{
    <div class="glass-card public-empty-state">
        <h2>Игры не найдены</h2>
        <p>Попробуйте изменить фильтры или загляните позже — новые сессии появляются каждый день.</p>
    </div>
}
else
{
    <div class="showcase-grid">
        @foreach (var session in sessions)
        {
            <article class="glass-card showcase-card animate-fade-in">
                <div class="showcase-card-image"
                     style="@(string.IsNullOrWhiteSpace(session.CoverImageUrl)
                         ? $"background: {GetGradientStyle(session.Id)}; background-size: cover; background-position: center;"
                         : $"background-image: url({session.CoverImageUrl}); background-size: cover; background-position: center;")">
                </div>
                <div class="showcase-card-body">
                    <div class="showcase-card-badges">
                        @if (!string.IsNullOrWhiteSpace(session.System))
                        {
                            <span class="status-badge status-info">@GetSystemDisplayName(session.System)</span>
                        }
                        @if (session.IsOneShot)
                        {
                            <span class="status-badge status-warning">Ваншот</span>
                        }
                        @if (!string.IsNullOrWhiteSpace(session.Format))
                        {
                            <span class="status-badge status-neutral">@TranslateFormat(session.Format)</span>
                        }
                    </div>
                    <h2 class="showcase-card-title">@session.Title</h2>
                    <div class="showcase-card-meta">
                        <span>@session.ScheduledAt.FormatMoscow()</span>
                        @if (session.DurationMinutes.HasValue)
                        {
                            <span>@FormatDuration(session.DurationMinutes.Value)</span>
                        }
                    </div>
                    <div class="showcase-card-seats">
                        <span>@FormatSeats(session)</span>
                    </div>
                    <div class="showcase-card-club">
                        <span>@session.GroupName</span>
                    </div>
                    @if (!string.IsNullOrWhiteSpace(session.MasterProfileSlug))
                    {
                        <div class="showcase-card-master">
                            <a href="@MasterProfilePath(session.MasterProfileSlug)">@(session.MasterDisplayName ?? "Профиль мастера")</a>
                        </div>
                    }
                    <div class="showcase-card-actions">
                        <a class="btn-gm btn-gm-outline" href="@($"/s/{session.Id}")">Подробнее</a>
                        @if (session.AllowDirectRegistration)
                        {
                            <a class="btn-gm btn-gm-primary" href="@($"/s/{session.Id}?register=1")">Записаться</a>
                        }
                    </div>
                </div>
            </article>
        }
    </div>

    @if (hasMore)
    {
        <div class="showcase-load-more">
            <button class="btn-gm btn-gm-primary" @onclick="LoadMoreAsync" disabled="@loading">
                @if (loading)
                {
                    <span>Загрузка...</span>
                }
                else
                {
                    <span>Загрузить ещё</span>
                }
            </button>
        </div>
    }
}

<style>
    .showcase-filters {
        display: flex;
        flex-wrap: wrap;
        gap: 1rem 1.5rem;
        margin-bottom: 1.5rem;
        padding: 1.25rem;
    }

    .showcase-filter-group {
        display: flex;
        flex-direction: column;
        gap: 0.375rem;
    }

    .showcase-filter-label {
        font-size: 0.75rem;
        font-weight: 600;
        color: var(--text-muted);
        text-transform: uppercase;
        letter-spacing: 0.05em;
        font-family: 'Jura', sans-serif;
    }

    .showcase-filter-buttons {
        display: flex;
        flex-wrap: wrap;
        gap: 0.375rem;
    }

    .showcase-filter-buttons .btn-gm {
        padding: 0.375rem 0.75rem;
        font-size: 0.8125rem;
    }

    .showcase-filter-select {
        min-width: 180px;
        width: auto;
    }

    .showcase-grid {
        display: grid;
        grid-template-columns: 1fr;
        gap: 1rem;
        margin-bottom: 1.5rem;
    }

    @@media (min-width: 640px) {
        .showcase-grid {
            grid-template-columns: repeat(2, 1fr);
        }
    }

    @@media (min-width: 1024px) {
        .showcase-grid {
            grid-template-columns: repeat(3, 1fr);
        }
    }

    .showcase-card {
        padding: 0;
        overflow: hidden;
        display: flex;
        flex-direction: column;
    }

    .showcase-card-image {
        height: 160px;
        background-size: cover;
        background-position: center;
    }

    .showcase-card-body {
        padding: 1rem;
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
        flex: 1;
    }

    .showcase-card-badges {
        display: flex;
        flex-wrap: wrap;
        gap: 0.375rem;
    }

    .showcase-card-title {
        font-size: 1.0625rem;
        margin: 0;
        font-family: 'Cinzel', serif;
        overflow-wrap: anywhere;
    }

    .showcase-card-meta,
    .showcase-card-seats,
    .showcase-card-club,
    .showcase-card-master {
        font-size: 0.8125rem;
        color: var(--text-secondary);
        font-family: 'Jura', sans-serif;
    }

    .showcase-card-club {
        color: var(--text-muted);
    }

    .showcase-card-master a {
        color: var(--accent-primary);
        text-decoration: none;
        font-weight: 600;
    }

    .showcase-card-actions {
        margin-top: auto;
        padding-top: 0.75rem;
        display: flex;
        gap: 0.5rem;
        flex-wrap: wrap;
    }

    .showcase-card-actions .btn-gm {
        flex: 1;
        justify-content: center;
    }

    .showcase-load-more {
        display: flex;
        justify-content: center;
        margin-bottom: 2rem;
    }

    .showcase-skeleton {
        padding: 0;
        overflow: hidden;
    }

    .showcase-skeleton-image {
        height: 160px;
        border-radius: 0;
    }

    .showcase-skeleton .showcase-card-body {
        padding: 1rem;
    }

    .showcase-skeleton .skeleton-text {
        margin-bottom: 0.5rem;
    }
</style>

@code {
    private ShowcaseFilter filter = new();
    private List<ShowcaseSessionDto> sessions = new();
    private bool loading;
    private bool hasMore;
    private int page = 1;
    private const int PageSize = 12;

    protected override async Task OnInitializedAsync()
    {
        await LoadAsync();
    }

    private async Task LoadAsync()
    {
        loading = true;
        try
        {
            page = 1;
            sessions.Clear();
            var results = await SessionStore.GetShowcaseSessionsAsync(filter, page, PageSize);
            sessions.AddRange(results);
            hasMore = results.Count == PageSize;
        }
        finally
        {
            loading = false;
        }
    }

    private async Task LoadMoreAsync()
    {
        if (loading)
            return;

        loading = true;
        try
        {
            page++;
            var results = await SessionStore.GetShowcaseSessionsAsync(filter, page, PageSize);
            sessions.AddRange(results);
            hasMore = results.Count == PageSize;
        }
        finally
        {
            loading = false;
        }
    }

    private async Task OnFilterChanged()
    {
        await LoadAsync();
    }

    private async Task SetDate(DateFilter value)
    {
        filter = filter with { Date = value };
        await OnFilterChanged();
    }

    private async Task SetSeats(SeatFilter value)
    {
        filter = filter with { Seats = value };
        await OnFilterChanged();
    }

    private async Task OnSystemChanged(ChangeEventArgs e)
    {
        var value = e.Value?.ToString();
        filter = filter with { System = string.IsNullOrWhiteSpace(value) ? null : value };
        await OnFilterChanged();
    }

    private async Task SetOneShot(bool? value)
    {
        filter = filter with { IsOneShot = value };
        await OnFilterChanged();
    }

    private async Task SetFormat(string? value)
    {
        filter = filter with { Format = value };
        await OnFilterChanged();
    }

    private static string GetGradientStyle(Guid id)
    {
        var bytes = id.ToByteArray();
        var hue1 = bytes[0] % 360;
        var hue2 = (bytes[1] + 120) % 360;
        return $"linear-gradient(135deg, hsl({hue1}, 55%, 28%) 0%, hsl({hue2}, 55%, 20%) 100%)";
    }

    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 FormatSeats(ShowcaseSessionDto session)
    {
        var seats = session.MaxPlayers.HasValue
            ? $"{session.ActivePlayerCount}/{session.MaxPlayers.Value}"
            : $"{session.ActivePlayerCount} игроков";

        if (session.WaitlistedPlayerCount > 0)
            seats += $", ожидание {session.WaitlistedPlayerCount}";

        return seats;
    }

    private static string FormatDuration(int minutes)
    {
        if (minutes < 60)
            return $"{minutes} мин";

        var hours = minutes / 60;
        var mins = minutes % 60;
        return mins > 0 ? $"{hours} ч {mins} мин" : $"{hours} ч";
    }

    private static string MasterProfilePath(string slug) => $"/gm/{slug}";

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