@page "/wishlist/{Id:int}"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
@rendermode InteractiveServer
@inject WishlistService Wishlists
@inject IDbContextFactory<ApplicationDbContext> DbFactory
@inject AuthenticationStateProvider AuthState
@inject NavigationManager Nav

<PageTitle>@(view?.Wishlist.Title ?? "Wishlist")</PageTitle>

@if (loading)
{
    <p>Loading…</p>
}
else if (view is null)
{
    <div class="alert alert-warning">This wishlist doesn't exist or you don't have access to it.</div>
    <a href="wishlists">Back to my wishlists</a>
}
else
{
    <div class="d-flex justify-content-between align-items-start mb-2">
        <div>
            <h1 class="mb-0">@view.Wishlist.Title</h1>
            @if (!string.IsNullOrWhiteSpace(view.Wishlist.Description))
            {
                <p class="text-secondary">@view.Wishlist.Description</p>
            }
            @if (!view.IsViewerOwner)
            {
                <span class="badge bg-info text-dark">Viewing @ownerName's list</span>
            }
        </div>
        @if (view.IsViewerOwner)
        {
            <div class="btn-group">
                <button class="btn btn-outline-secondary btn-sm" @onclick="() => showSettings = !showSettings">Settings</button>
                <button class="btn btn-primary btn-sm" @onclick="StartAddItem">+ Add item</button>
            </div>
        }
    </div>

    @if (view.IsViewerOwner)
    {
        <div class="alert alert-secondary py-2 small">
            🤫 To keep the surprise, claims on your own list are hidden from you.
        </div>
    }

    @if (showSettings && view.IsViewerOwner)
    {
        <div class="card mb-3">
            <div class="card-body">
                <h5 class="card-title">List settings</h5>
                <EditForm Model="settings" OnValidSubmit="SaveSettings">
                    <div class="mb-2">
                        <label class="form-label">Title</label>
                        <InputText class="form-control" @bind-Value="settings.Title" />
                    </div>
                    <div class="mb-2">
                        <label class="form-label">Description</label>
                        <InputTextArea class="form-control" @bind-Value="settings.Description" rows="2" />
                    </div>
                    <div class="mb-2">
                        <label class="form-label">Who can see this list?</label>
                        <InputSelect class="form-select" @bind-Value="settings.Visibility">
                            <option value="@WishlistVisibility.AllMembers">All members</option>
                            <option value="@WishlistVisibility.SpecificUsers">Only specific people</option>
                        </InputSelect>
                    </div>
                    @if (settings.Visibility == WishlistVisibility.SpecificUsers)
                    {
                        <div class="mb-2 border rounded p-2">
                            <div class="small text-secondary mb-1">Share with:</div>
                            @if (allUsers.Count == 0)
                            {
                                <div class="text-secondary small">No other users yet.</div>
                            }
                            @foreach (var u in allUsers)
                            {
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" id="@($"share-{u.Id}")"
                                           checked="@shareWith.Contains(u.Id)"
                                           @onchange="e => ToggleShare(u.Id, (bool)e.Value!)" />
                                    <label class="form-check-label" for="@($"share-{u.Id}")">@u.DisplayName</label>
                                </div>
                            }
                        </div>
                    }
                    <div class="form-check mb-2">
                        <InputCheckbox class="form-check-input" id="archived" @bind-Value="settings.IsArchived" />
                        <label class="form-check-label" for="archived">Archived (hidden from others)</label>
                    </div>
                    <button type="submit" class="btn btn-success btn-sm">Save settings</button>
                    <button type="button" class="btn btn-link btn-sm" @onclick="() => showSettings = false">Cancel</button>
                </EditForm>
            </div>
        </div>
    }

    @if (addingItem && view.IsViewerOwner)
    {
        <ItemEditor WishlistId="view.Wishlist.Id" OnSaved="OnItemSaved" OnCancelled="() => addingItem = false" />
    }

    @if (claimError is not null)
    {
        <div class="alert alert-warning py-2">@claimError</div>
    }

    @if (view.Items.Count == 0)
    {
        <p class="text-secondary">No items yet.</p>
    }
    else
    {
        <div class="row g-3">
            @foreach (var iv in view.Items)
            {
                <div class="col-md-6">
                    @if (editingItemId == iv.Item.Id && view.IsViewerOwner)
                    {
                        <ItemEditor WishlistId="view.Wishlist.Id" Item="iv.Item"
                                    OnSaved="OnItemSaved" OnCancelled="() => editingItemId = null" />
                    }
                    else
                    {
                        var item = iv.Item;
                        <div class="card h-100 @(iv.IsFullyClaimed ? "border-success" : "")">
                            <div class="row g-0 h-100">
                                @{
                                    string? img = item.ImageKind == ImageKind.Uploaded && item.ImagePath is not null
                                        ? $"/uploads/{item.ImagePath}"
                                        : null;
                                }
                                @if (img is not null)
                                {
                                    <div class="col-4">
                                        <img src="@img" alt="@item.Name" class="img-fluid rounded-start"
                                             style="object-fit:cover;height:100%;width:100%;" />
                                    </div>
                                }
                                <div class="@(img is not null ? "col-8" : "col-12")">
                                    <div class="card-body">
                                        <div class="d-flex justify-content-between">
                                            <h5 class="card-title mb-1">@item.Name</h5>
                                            <span class="badge bg-light text-dark" title="Priority">P@(item.Priority)</span>
                                        </div>
                                        @if (!string.IsNullOrWhiteSpace(item.Description))
                                        {
                                            <p class="card-text small">@item.Description</p>
                                        }
                                        <div class="small text-secondary mb-2">
                                            @if (item.Price is not null)
                                            {
                                                <span class="me-2">@item.Price.Value.ToString("C")</span>
                                            }
                                            @if (item.Quantity > 1)
                                            {
                                                <span>Qty wanted: @item.Quantity</span>
                                            }
                                        </div>
                                        @if (!string.IsNullOrWhiteSpace(item.ProductUrl))
                                        {
                                            <a href="@item.ProductUrl" target="_blank" rel="noopener" class="btn btn-outline-secondary btn-sm mb-2">View product ↗</a>
                                        }

                                        @if (view!.IsViewerOwner)
                                        {
                                            <div class="mt-2">
                                                <button class="btn btn-outline-primary btn-sm" @onclick="() => editingItemId = item.Id">Edit</button>
                                                <button class="btn btn-outline-danger btn-sm" @onclick="() => DeleteItem(item.Id)">Delete</button>
                                            </div>
                                        }
                                        else
                                        {
                                            <div class="mt-2 border-top pt-2">
                                                @if (iv.ClaimedByViewer)
                                                {
                                                    <div class="text-success small mb-1">✓ You've claimed this</div>
                                                    <button class="btn btn-outline-secondary btn-sm" @onclick="() => UnclaimItem(iv)">Unclaim</button>
                                                }
                                                else if (iv.RemainingQuantity > 0)
                                                {
                                                    @if (item.Quantity > 1)
                                                    {
                                                        <div class="input-group input-group-sm mb-1" style="max-width:160px;">
                                                            <span class="input-group-text">Qty</span>
                                                            <input type="number" class="form-control" min="1" max="@iv.RemainingQuantity"
                                                                   value="@GetClaimQty(iv)"
                                                                   @onchange="e => claimQty[item.Id] = int.TryParse(e.Value?.ToString(), out var v) ? v : 1" />
                                                        </div>
                                                        <div class="small text-secondary mb-1">@iv.RemainingQuantity of @item.Quantity left</div>
                                                    }
                                                    <button class="btn btn-success btn-sm" @onclick="() => ClaimItem(iv)">Claim</button>
                                                }
                                                else
                                                {
                                                    <div class="text-success small">Fully claimed</div>
                                                }

                                                @if (iv.OtherClaims.Count > 0)
                                                {
                                                    <div class="small text-secondary mt-2">
                                                        Also claimed by:
                                                        @string.Join(", ", iv.OtherClaims.Select(c => $"{c.ClaimedByDisplayName} (×{c.Quantity})"))
                                                    </div>
                                                }
                                            </div>
                                        }
                                    </div>
                                </div>
                            </div>
                        </div>
                    }
                </div>
            }
        </div>
    }
}

@code {
    [Parameter] public int Id { get; set; }

    private WishlistDetailView? view;
    private bool loading = true;
    private string? userId;
    private string ownerName = "";

    private bool showSettings;
    private bool addingItem;
    private int? editingItemId;

    // claim input state, keyed by item id
    private readonly Dictionary<int, int> claimQty = new();
    private string? claimError;

    // settings state
    private SettingsModel settings = new();
    private List<ApplicationUser> allUsers = new();
    private HashSet<string> shareWith = new();

    protected override async Task OnInitializedAsync()
    {
        userId = await AuthState.GetUserIdAsync();
        await LoadAsync();
    }

    protected override async Task OnParametersSetAsync()
    {
        if (!loading && view?.Wishlist.Id != Id)
            await LoadAsync();
    }

    private async Task LoadAsync()
    {
        loading = true;
        if (userId is null) { loading = false; return; }
        view = await Wishlists.GetDetailAsync(Id, userId);
        if (view is not null)
        {
            ownerName = view.Wishlist.Owner?.DisplayName ?? "";
            if (view.IsViewerOwner)
            {
                if (string.IsNullOrEmpty(ownerName)) ownerName = "you";
                settings = new SettingsModel
                {
                    Title = view.Wishlist.Title,
                    Description = view.Wishlist.Description,
                    Visibility = view.Wishlist.Visibility,
                    IsArchived = view.Wishlist.IsArchived,
                };
                shareWith = view.Wishlist.Shares.Select(s => s.UserId).ToHashSet();
                await using var db = await DbFactory.CreateDbContextAsync();
                allUsers = await db.Users.Where(u => u.Id != userId)
                    .OrderBy(u => u.DisplayName).ToListAsync();
            }
            else
            {
                // resolve owner name if not loaded
                if (string.IsNullOrEmpty(ownerName))
                {
                    await using var db = await DbFactory.CreateDbContextAsync();
                    var owner = await db.Users.FindAsync(view.Wishlist.OwnerId);
                    ownerName = owner?.DisplayName ?? "someone";
                }
            }
        }
        loading = false;
    }

    private void StartAddItem()
    {
        editingItemId = null;
        addingItem = true;
    }

    private async Task OnItemSaved()
    {
        addingItem = false;
        editingItemId = null;
        await LoadAsync();
    }

    private async Task DeleteItem(int itemId)
    {
        await using var db = await DbFactory.CreateDbContextAsync();
        await db.WishlistItems.Where(i => i.Id == itemId).ExecuteDeleteAsync();
        await LoadAsync();
    }

    // --- Claims (non-owner) --------------------------------------------------------------------

    private int GetClaimQty(WishlistItemView iv)
    {
        if (!claimQty.TryGetValue(iv.Item.Id, out var q))
            q = Math.Min(1, iv.RemainingQuantity);
        return Math.Max(1, q);
    }

    private async Task ClaimItem(WishlistItemView iv)
    {
        claimError = null;
        var result = await Wishlists.ClaimAsync(iv.Item.Id, userId!, GetClaimQty(iv), null);
        if (!result.Succeeded) claimError = result.Error;
        await LoadAsync();
    }

    private async Task UnclaimItem(WishlistItemView iv)
    {
        claimError = null;
        var result = await Wishlists.UnclaimAsync(iv.Item.Id, userId!);
        if (!result.Succeeded) claimError = result.Error;
        await LoadAsync();
    }

    // --- Settings (owner) ----------------------------------------------------------------------

    private async Task SaveSettings()
    {
        await using var db = await DbFactory.CreateDbContextAsync();
        var w = await db.Wishlists.Include(x => x.Shares).FirstAsync(x => x.Id == Id);
        w.Title = settings.Title.Trim();
        w.Description = settings.Description;
        w.Visibility = settings.Visibility;
        w.IsArchived = settings.IsArchived;

        w.Shares.Clear();
        if (settings.Visibility == WishlistVisibility.SpecificUsers)
        {
            foreach (var uid in shareWith)
                w.Shares.Add(new WishlistShare { WishlistId = w.Id, UserId = uid });
        }
        await db.SaveChangesAsync();
        showSettings = false;
        await LoadAsync();
    }

    private void ToggleShare(string uid, bool on)
    {
        if (on) shareWith.Add(uid); else shareWith.Remove(uid);
    }

    private sealed class SettingsModel
    {
        public string Title { get; set; } = "";
        public string? Description { get; set; }
        public WishlistVisibility Visibility { get; set; }
        public bool IsArchived { get; set; }
    }
}
