@page "/portfolio/manage/{PortfolioGameId:guid}"
@using GmRelay.Web.Services
@using GmRelay.Web.Services.Portfolio
@using GmRelay.Web.Services.Portfolio.Covers
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@attribute [Authorize]
@inject AuthorizedPortfolioService PortfolioService
@inject AuthenticationStateProvider AuthStateProvider
@inject NavigationManager Navigation

<PageTitle>Портфолио — GM-Relay</PageTitle>

<div class="page-container">
    <ul class="gm-breadcrumb animate-fade-in">
        <li><a href="/">Главная</a></li>
        <li><a href="/group/@groupId">Группа</a></li>
        <li class="active">Портфолио</li>
    </ul>

    <div class="page-header animate-fade-in">
        <h2>📚 Управление портфолио</h2>
        @if (editor is not null)
        {
            <p style="color: var(--text-muted); margin-top: 0.25rem;">@editor.Title</p>
        }
    </div>

    @if (!string.IsNullOrEmpty(errorMessage))
    {
        <div class="gm-alert gm-alert-danger" style="margin-bottom: 1rem;">
            ⚠️ @errorMessage
        </div>
    }

    @if (!string.IsNullOrEmpty(successMessage))
    {
        <div class="gm-alert gm-alert-success" style="margin-bottom: 1rem;">
            ✅ @successMessage
        </div>
    }

    @if (editor is null)
    {
        <div class="glass-card" style="padding: 2rem;">
            <div class="skeleton skeleton-text" style="width: 70%; margin-bottom: 1rem;"></div>
            <div class="skeleton skeleton-text" style="width: 50%; margin-bottom: 0.75rem;"></div>
            <div class="skeleton skeleton-text" style="width: 60%;"></div>
        </div>
    }
    else
    {
        <div class="glass-card animate-slide-up" style="margin-bottom: 1rem;">
            <div class="batch-bulk-header">
                <div>
                    <h3>Параметры публикации</h3>
                    <p>Управление видимостью и обложкой приключения.</p>
                </div>
                <span class="status-badge @(editor.IsPublic ? "status-success" : "status-neutral")">
                    @(editor.IsPublic ? "Опубликовано" : "Черновик")
                </span>
            </div>

            <div class="portfolio-editor-grid">
                <div class="portfolio-editor-cover">
                    @if (!string.IsNullOrEmpty(editor.CoverPath))
                    {
                        <img src="@editor.CoverPath" alt="Обложка" class="portfolio-editor-cover-image" />
                    }
                    else
                    {
                        <div class="portfolio-editor-cover-empty">Обложка не загружена</div>
                    }
                    <InputFile OnChange="HandleFileSelected" accept="image/jpeg,image/png,image/webp" class="portfolio-editor-cover-input" />
                    <button type="button" class="btn-gm btn-gm-outline" disabled="@isUploadingCover" @onclick="TriggerCoverUpload">
                        @(isUploadingCover ? "⏳ Загружаем..." : "🖼 Заменить обложку")
                    </button>
                </div>

                <div class="portfolio-editor-fields">
                    <EditForm Model="@editorModel" OnValidSubmit="SaveDraft">
                        <div class="gm-form-group">
                            <label class="gm-form-label">Название</label>
                            <InputText @bind-Value="editorModel.Title" class="gm-form-control" />
                        </div>
                        <div class="gm-form-group">
                            <label class="gm-form-label">Короткий адрес (slug)</label>
                            <InputText @bind-Value="editorModel.PublicSlug" class="gm-form-control" />
                            <div class="gm-form-hint">Латиница, цифры и дефисы, например "night-city-run".</div>
                        </div>
                        <div class="gm-form-group">
                            <label class="gm-form-label">Система</label>
                            <InputText @bind-Value="editorModel.System" class="gm-form-control" />
                        </div>
                        <div class="gm-form-group">
                            <label class="gm-form-label">Формат</label>
                            <InputText @bind-Value="editorModel.Format" class="gm-form-control" />
                        </div>
                        <div class="gm-form-group">
                            <label class="gm-form-label">Описание</label>
                            <InputTextArea @bind-Value="editorModel.Description" class="gm-form-control" />
                        </div>

                        <div class="portfolio-editor-actions">
                            <button type="submit" class="btn-gm btn-gm-primary" disabled="@isSaving">
                                @(isSaving ? "⏳ Сохраняем..." : "💾 Сохранить")
                            </button>
                        </div>
                    </EditForm>

                    <div class="portfolio-editor-publish-row">
                        <button type="button" class="btn-gm @(editor.IsPublic ? "btn-gm-outline" : "btn-gm-success")" disabled="@isUpdatingPublication" @onclick="() => SetPublication(!editor.IsPublic)">
                            @(isUpdatingPublication
                                ? "Обновляем..."
                                : editor.IsPublic ? "Скрыть из каталога" : "Опубликовать")
                        </button>
                        <button type="button" class="btn-gm btn-gm-danger" disabled="@isDeleting" @onclick="DeletePortfolio">
                            @(isDeleting ? "⏳ Удаляем..." : "🗑 Удалить")
                        </button>
                    </div>
                </div>
            </div>
        </div>

        <div class="glass-card animate-slide-up" style="margin-bottom: 1rem;">
            <div class="batch-bulk-header">
                <div>
                    <h3>Проведённые сессии</h3>
                    <p>Отметьте игры, которые вошли в это приключение.</p>
                </div>
                <span class="status-badge status-info">@editorModel.SessionIds.Count</span>
            </div>
            <div class="portfolio-option-list">
                @foreach (var session in editor.Sessions)
                {
                    <label class="portfolio-option-row">
                        <input type="checkbox" checked="@session.Selected" @onchange="e => ToggleSession(session.Id, (bool)(e.Value ?? false))" />
                        <span class="portfolio-option-title">@session.Title</span>
                        <span class="portfolio-option-meta">@session.ScheduledAt.FormatMoscow()</span>
                    </label>
                }
            </div>
        </div>

        <div class="glass-card animate-slide-up" style="margin-bottom: 1rem;">
            <div class="batch-bulk-header">
                <div>
                    <h3>Мастера приключения</h3>
                    <p>Выберите мастеров, которые вели это приключение.</p>
                </div>
                <span class="status-badge status-info">@editorModel.MasterPlayerIds.Count</span>
            </div>
            <div class="portfolio-option-list">
                @foreach (var master in editor.Masters)
                {
                    <label class="portfolio-option-row">
                        <input type="checkbox" checked="@master.Selected" @onchange="e => ToggleMaster(master.PlayerId, (bool)(e.Value ?? false))" />
                        <span class="portfolio-option-title">@master.DisplayName</span>
                    </label>
                }
            </div>
        </div>

        <div class="glass-card animate-slide-up" style="margin-bottom: 1rem;">
            <div class="batch-bulk-header">
                <div>
                    <h3>Модерация отзывов</h3>
                    <p>Одобрите, отклоните или скройте отзывы игроков перед публикацией.</p>
                </div>
                <span class="status-badge @(editor.Reviews.Any(r => r.ModerationStatus == "Pending") ? "status-warning" : "status-neutral")">
                    @editor.Reviews.Count(r => r.ModerationStatus == "Pending") на модерации
                </span>
            </div>

            @if (editor.Reviews.Count == 0)
            {
                <div class="empty-state empty-state-compact">
                    <div class="empty-state-title">Отзывов пока нет</div>
                    <p class="empty-state-text">Игроки смогут оставить отзыв после публикации приключения.</p>
                </div>
            }
            else
            {
                <div class="portfolio-review-moderation">
                    @foreach (var review in editor.Reviews)
                    {
                        <div class="portfolio-review-row">
                            <div class="portfolio-review-meta">
                                <span class="portfolio-review-author">@review.AuthorDisplayName</span>
                                <span class="status-badge @GetReviewStatusClass(review.ModerationStatus)">@TranslateReviewStatus(review.ModerationStatus)</span>
                                <span class="portfolio-review-date">@review.CreatedAt.ToString("dd.MM.yyyy HH:mm")</span>
                            </div>
                            <p class="portfolio-review-body">@review.Body</p>
                            <div class="portfolio-review-actions">
                                <button type="button" class="btn-gm btn-gm-success" disabled="@(moderatingReviewId == review.Id)" @onclick="@(() => Moderate(review.Id, "Approved"))">
                                    @(moderatingReviewId == review.Id ? "⏳..." : "Одобрить")
                                </button>
                                <button type="button" class="btn-gm btn-gm-outline" disabled="@(moderatingReviewId == review.Id)" @onclick="@(() => Moderate(review.Id, "Rejected"))">
                                    @(moderatingReviewId == review.Id ? "⏳..." : "Отклонить")
                                </button>
                                <button type="button" class="btn-gm btn-gm-danger" disabled="@(moderatingReviewId == review.Id)" @onclick="@(() => Moderate(review.Id, "Hidden"))">
                                    @(moderatingReviewId == review.Id ? "⏳..." : "Скрыть")
                                </button>
                            </div>
                        </div>
                    }
                </div>
            }
        </div>
    }
</div>

@code {
    [Parameter] public Guid PortfolioGameId { get; set; }

    private PortfolioGameEditor? editor;
    private PortfolioEditorModel editorModel = new();
    private Guid? groupId;
    private string? errorMessage;
    private string? successMessage;
    private bool isSaving;
    private bool isUploadingCover;
    private bool isUpdatingPublication;
    private bool isDeleting;
    private Guid? moderatingReviewId;
    private IBrowserFile? pendingCoverFile;

    protected override async Task OnParametersSetAsync()
    {
        await Reload();
    }

    private async Task Reload()
    {
        editor = await PortfolioService.GetPortfolioGameForCurrentUserAsync(PortfolioGameId);
        if (editor is null)
        {
            Navigation.NavigateTo("/access-denied");
            return;
        }

        groupId = editor.GroupId;
        editorModel = new PortfolioEditorModel
        {
            Title = editor.Title,
            PublicSlug = editor.PublicSlug ?? string.Empty,
            Description = editor.Description ?? string.Empty,
            System = editor.System ?? string.Empty,
            Format = editor.Format ?? string.Empty,
            SessionIds = editor.Sessions.Where(s => s.Selected).Select(s => s.Id).ToList(),
            MasterPlayerIds = editor.Masters.Where(m => m.Selected).Select(m => m.PlayerId).ToList()
        };
    }

    private void ToggleSession(Guid sessionId, bool isChecked)
    {
        if (isChecked)
        {
            if (!editorModel.SessionIds.Contains(sessionId))
            {
                editorModel.SessionIds.Add(sessionId);
            }
        }
        else
        {
            editorModel.SessionIds.Remove(sessionId);
        }
    }

    private void ToggleMaster(Guid playerId, bool isChecked)
    {
        if (isChecked)
        {
            if (!editorModel.MasterPlayerIds.Contains(playerId))
            {
                editorModel.MasterPlayerIds.Add(playerId);
            }
        }
        else
        {
            editorModel.MasterPlayerIds.Remove(playerId);
        }
    }

    private async Task SaveDraft()
    {
        errorMessage = null;
        successMessage = null;
        isSaving = true;

        try
        {
            await PortfolioService.UpdateDraftForCurrentUserAsync(
                PortfolioGameId,
                new PortfolioGameUpdate(
                    editorModel.Title,
                    editorModel.PublicSlug,
                    editorModel.Description,
                    editorModel.System,
                    editorModel.Format,
                    editorModel.SessionIds,
                    editorModel.MasterPlayerIds));
            successMessage = "Черновик сохранён.";
            await Reload();
        }
        catch (InvalidOperationException ex)
        {
            errorMessage = ex.Message;
        }
        catch (Exception ex)
        {
            errorMessage = "Не удалось сохранить: " + ex.Message;
        }
        finally
        {
            isSaving = false;
        }
    }

    private void TriggerCoverUpload()
    {
        // The InputFile control is rendered with a label. No-op click handler kept for symmetry.
    }

    private async Task HandleFileSelected(InputFileChangeEventArgs e)
    {
        var file = e.File;
        if (file is null)
        {
            return;
        }

        pendingCoverFile = file;
        errorMessage = null;
        successMessage = null;
        isUploadingCover = true;

        try
        {
            await using var stream = file.OpenReadStream(LocalPortfolioCoverStorage.MaxBytes);
            await PortfolioService.ReplaceCoverForCurrentUserAsync(PortfolioGameId, stream, file.ContentType);
            successMessage = "Обложка обновлена.";
            await Reload();
        }
        catch (InvalidOperationException ex)
        {
            errorMessage = ex.Message;
        }
        catch (Exception ex)
        {
            errorMessage = "Не удалось загрузить обложку: " + ex.Message;
        }
        finally
        {
            isUploadingCover = false;
            pendingCoverFile = null;
        }
    }

    private async Task SetPublication(bool isPublic)
    {
        errorMessage = null;
        successMessage = null;
        isUpdatingPublication = true;

        try
        {
            await PortfolioService.SetPublicationForCurrentUserAsync(PortfolioGameId, isPublic);
            successMessage = isPublic ? "Приключение опубликовано." : "Приключение скрыто.";
            await Reload();
        }
        catch (InvalidOperationException ex)
        {
            errorMessage = ex.Message;
        }
        catch (Exception ex)
        {
            errorMessage = "Не удалось обновить публикацию: " + ex.Message;
        }
        finally
        {
            isUpdatingPublication = false;
        }
    }

    private async Task DeletePortfolio()
    {
        errorMessage = null;
        successMessage = null;
        isDeleting = true;

        try
        {
            await PortfolioService.DeleteForCurrentUserAsync(PortfolioGameId);
            Navigation.NavigateTo(groupId.HasValue ? $"/group/{groupId.Value}" : "/");
        }
        catch (Exception ex)
        {
            errorMessage = "Не удалось удалить: " + ex.Message;
            isDeleting = false;
        }
    }

    private async Task Moderate(Guid reviewId, string moderationStatus)
    {
        errorMessage = null;
        successMessage = null;
        moderatingReviewId = reviewId;

        try
        {
            await PortfolioService.ModerateReviewForCurrentUserAsync(PortfolioGameId, reviewId, moderationStatus);
            successMessage = "Модерация обновлена.";
            await Reload();
        }
        catch (InvalidOperationException ex)
        {
            errorMessage = ex.Message;
        }
        catch (Exception ex)
        {
            errorMessage = "Не удалось обновить отзыв: " + ex.Message;
        }
        finally
        {
            moderatingReviewId = null;
        }
    }

    private static string GetReviewStatusClass(string status) => status switch
    {
        "Approved" => "status-success",
        "Rejected" => "status-danger",
        "Hidden" => "status-warning",
        _ => "status-neutral"
    };

    private static string TranslateReviewStatus(string status) => status switch
    {
        "Approved" => "Одобрен",
        "Rejected" => "Отклонён",
        "Hidden" => "Скрыт",
        _ => "На модерации"
    };

    private sealed class PortfolioEditorModel
    {
        public string Title { get; set; } = string.Empty;
        public string PublicSlug { get; set; } = string.Empty;
        public string Description { get; set; } = string.Empty;
        public string System { get; set; } = string.Empty;
        public string Format { get; set; } = string.Empty;
        public List<Guid> SessionIds { get; set; } = new();
        public List<Guid> MasterPlayerIds { get; set; } = new();
    }
}
