@page "/items/{id:guid}"
@inherits MainBase
@inject ItemService ItemService
@implements IAsyncDisposable
@using Microsoft.Extensions.Localization
@using AliasClientDb
@using AliasClientDb.Models
@using AliasVault.Client.Main.Models
@using AliasVault.Client.Main.Utilities
@using AliasVault.Client.Main.Components.Items
@using AliasVault.Client.Main.Components.Fields

<LayoutPageTitle>@Localizer["ViewItemPageTitle"]</LayoutPageTitle>

@if (IsLoading || Item == null)
{
    <LoadingIndicator />
}
else
{
    <PageHeader
        BreadcrumbItems="@BreadcrumbItems"
        Title="@Localizer["ViewItemTitle"]">
        <CustomActions>
            <LinkButton
                SmallText="@Localizer["EditButtonMobile"]"
                Text="@Localizer["EditButtonDesktop"]"
                Href="@($"/items/{Id}/edit")"
                Color="primary" />
            <button type="button" @onclick="OpenDeleteModal" class="@ButtonStyles.BaseClasses @ButtonStyles.GetColorClasses("danger")">
                <span class="md:hidden">@Localizer["DeleteButtonMobile"]</span>
                <span class="hidden md:inline">@Localizer["DeleteButtonDesktop"]</span>
            </button>
        </CustomActions>
    </PageHeader>

    <PageContent>
    <div class="grid grid-cols-1 px-4 md:grid-cols-2 lg:grid-cols-3 lg:gap-4 dark:bg-gray-900">
        @* Left column *@
        <div class="col-span-1 md:col-span-2 lg:col-span-1">
            @* Header block with icon and name *@
            <div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
                <div class="items-center flex space-x-4">
                    <ItemIcon
                        ItemType="@(Item.ItemType ?? ItemType.Login)"
                        LogoDataUri="@LogoConverter.ToDataUri(Item.Logo?.FileData)"
                        CardNumber="@GetCardNumber()"
                        AltText="@(Item.Name ?? "Item")"
                        SizeClass="w-14 h-14" />

                    <div class="flex-1 min-w-0">
                        <h3 class="mb-1 text-xl font-bold text-gray-900 dark:text-white truncate">@(Item.Name ?? Localizer["Untitled"])</h3>
                        @foreach (var url in UrlValues)
                        {
                            <div class="text-sm truncate">
                                @if (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
                                {
                                    <a href="@url" target="_blank" rel="noopener noreferrer" class="text-blue-500 break-all dark:text-blue-400 hover:underline">@url</a>
                                }
                                else
                                {
                                    <span class="text-gray-700 break-all dark:text-gray-300">@url</span>
                                }
                            </div>
                        }
                        @if (Folder != null)
                        {
                            <a href="/items/folder/@Folder.Id" class="inline-flex items-center gap-2 mt-2 px-3 py-1.5 text-sm font-medium text-gray-600 dark:text-gray-400 bg-gray-100 dark:bg-gray-700 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors">
                                <svg class="w-4 h-4 text-orange-500" viewBox="0 0 24 24" fill="currentColor">
                                    <path d="M10 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-8l-2-2z"/>
                                </svg>
                                <span>@Folder.Name</span>
                            </a>
                        }
                    </div>
                </div>
            </div>

            @* Recent emails - only for Login/Alias *@
            @if ((Item.ItemType == ItemType.Login || Item.ItemType == ItemType.Alias) && !string.IsNullOrEmpty(GetEmailAddress()))
            {
                <RecentEmails EmailAddress="@GetEmailAddress()" />
            }

            @* TOTP codes - only for items with TOTP *@
            @if (Item.TotpCodes.Any(t => !t.IsDeleted))
            {
                <TotpViewer TotpCodeList="@Item.TotpCodes.Where(t => !t.IsDeleted).ToList()" />
            }

            @* Notes - if present (left column for non-Note types) *@
            @if (Item.ItemType != ItemType.Note && GroupedFields.TryGetValue(FieldCategory.Notes, out var notesFields) && notesFields.Count > 0)
            {
                <div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
                    <h3 class="mb-4 text-xl font-semibold dark:text-white">@Localizer["NotesSection"]</h3>
                    <div class="grid grid-cols-6 gap-6">
                        @foreach (var field in notesFields)
                        {
                            <FieldBlock Field="@field" ItemId="@Item.Id" HideLabel="true" />
                        }
                    </div>
                </div>
            }

            @* Attachments *@
            @if (Item.Attachments.Any(a => !a.IsDeleted))
            {
                <AttachmentViewer Attachments="@Item.Attachments" />
            }
        </div>

        @* Right column *@
        <div class="col-span-1 md:col-span-2 lg:col-span-2">
            @* Login fields - for Login/Alias *@
            @if ((Item.ItemType == ItemType.Login || Item.ItemType == ItemType.Alias) &&
                GroupedFields.TryGetValue(FieldCategory.Login, out var loginFields) && loginFields.Count > 0)
            {
                <div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
                    <h3 class="mb-2 text-xl font-semibold dark:text-white">@Localizer["LoginDetailsSection"]</h3>
                    <p class="mb-4 text-sm text-gray-600 dark:text-gray-400">
                        @{
                            var email = GetEmailAddress();
                        }
                        @if (EmailService.IsAliasVaultSupportedDomain(email ?? string.Empty))
                        {
                            <span>@Localizer["GeneratedItemDescription"]</span>
                        }
                        else
                        {
                            <span>@Localizer["StoredItemDescription"]</span>
                        }
                    </p>

                    @* Show passkey if available *@
                    @if (Item.Passkeys != null && Item.Passkeys.Any())
                    {
                        var passkey = Item.Passkeys.First();
                        <div class="mb-6 p-3 rounded-lg bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700">
                            <div class="flex items-start gap-3">
                                <svg class="w-5 h-5 text-gray-600 dark:text-gray-400 mt-0.5 flex-shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                    <path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4" />
                                </svg>
                                <div class="flex-1">
                                    <div class="mb-1">
                                        <span class="text-sm font-semibold text-gray-900 dark:text-white">@Localizer["PasskeyLabel"]</span>
                                    </div>
                                    <div class="space-y-1 mb-2">
                                        @if (!string.IsNullOrWhiteSpace(passkey.RpId))
                                        {
                                            <div>
                                                <span class="text-xs text-gray-500 dark:text-gray-400">@Localizer["PasskeySiteLabel"]: </span>
                                                <span class="text-sm text-gray-900 dark:text-white">@passkey.RpId</span>
                                            </div>
                                        }
                                        @if (!string.IsNullOrWhiteSpace(passkey.DisplayName))
                                        {
                                            <div>
                                                <span class="text-xs text-gray-500 dark:text-gray-400">@Localizer["PasskeyDisplayNameLabel"]: </span>
                                                <span class="text-sm text-gray-900 dark:text-white">@passkey.DisplayName</span>
                                            </div>
                                        }
                                    </div>
                                    <p class="text-xs text-gray-600 dark:text-gray-400">
                                        @Localizer["PasskeyHelpText"]
                                    </p>
                                </div>
                            </div>
                        </div>
                    }

                    <form action="#">
                        <div class="grid grid-cols-6 gap-6">
                            @foreach (var field in loginFields)
                            {
                                <FieldBlock Field="@field" ItemId="@Item.Id" FullWidth="@LayoutUtils.ShouldBeFullWidth(field, loginFields)" />
                            }
                        </div>
                    </form>
                </div>
            }

            @* Alias fields - for Alias type only *@
            @if (Item.ItemType == ItemType.Alias &&
                GroupedFields.TryGetValue(FieldCategory.Alias, out var aliasFields) && aliasFields.Count > 0)
            {
                <div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
                    <h3 class="mb-4 text-xl font-semibold dark:text-white">@Localizer["AliasSection"]</h3>
                    <form action="#">
                        <div class="grid grid-cols-6 gap-6">
                            @* Show full name if first and last name exist *@
                            @{
                                var firstName = aliasFields.FirstOrDefault(f => f.FieldKey == FieldKey.AliasFirstName)?.Value;
                                var lastName = aliasFields.FirstOrDefault(f => f.FieldKey == FieldKey.AliasLastName)?.Value;
                            }
                            @if (!string.IsNullOrWhiteSpace(firstName) && !string.IsNullOrWhiteSpace(lastName))
                            {
                                <div class="col-span-6">
                                    <CopyPasteFormRow Label="@Localizer["FullNameLabel"]" Value="@($"{firstName} {lastName}")" />
                                </div>
                            }
                            @foreach (var field in aliasFields)
                            {
                                <FieldBlock Field="@field" ItemId="@Item.Id" FullWidth="@LayoutUtils.ShouldBeFullWidth(field, aliasFields)" />
                            }
                        </div>
                    </form>
                </div>
            }

            @* Card fields - for CreditCard type *@
            @if (Item.ItemType == ItemType.CreditCard &&
                GroupedFields.TryGetValue(FieldCategory.Card, out var cardFields) && cardFields.Count > 0)
            {
                <div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
                    <h3 class="mb-4 text-xl font-semibold dark:text-white">@Localizer["CardSection"]</h3>
                    <form action="#">
                        <div class="grid grid-cols-6 gap-6">
                            @foreach (var field in cardFields)
                            {
                                <FieldBlock Field="@field" ItemId="@Item.Id" FullWidth="@LayoutUtils.ShouldBeFullWidth(field, cardFields)" />
                            }
                        </div>
                    </form>
                </div>
            }

            @* Notes - for Note type (main content area) *@
            @if (Item.ItemType == ItemType.Note && GroupedFields.TryGetValue(FieldCategory.Notes, out var noteTypeNotesFields) && noteTypeNotesFields.Count > 0)
            {
                <div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
                    <h3 class="mb-4 text-xl font-semibold dark:text-white">@Localizer["NotesSection"]</h3>
                    <div class="grid grid-cols-6 gap-6">
                        @foreach (var field in noteTypeNotesFields)
                        {
                            <FieldBlock Field="@field" ItemId="@Item.Id" HideLabel="true" />
                        }
                    </div>
                </div>
            }

            @* Custom fields *@
            @if (GroupedFields.TryGetValue(FieldCategory.Custom, out var customFields) && customFields.Count > 0)
            {
                <div class="p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
                    <form action="#">
                        <div class="grid grid-cols-6 gap-6">
                            @foreach (var field in customFields)
                            {
                                <FieldBlock Field="@field" ItemId="@Item.Id" FullWidth="true" />
                            }
                        </div>
                    </form>
                </div>
            }
        </div>
    </div>
    </PageContent>

    <FormModal
        IsOpen="ShowDeleteModal"
        Title="@DeleteLocalizer["DeleteItemTitle"]"
        IconBackgroundClass="bg-red-100 dark:bg-red-900/30"
        ConfirmText="@DeleteLocalizer["YesImSureButton"]"
        CancelText="@DeleteLocalizer["NoCancelButton"]"
        ConfirmButtonClass="bg-red-600 hover:bg-red-700"
        IsLoading="IsDeleting"
        OnConfirm="ConfirmDelete"
        OnClose="CancelDelete">
        <Icon>
            <svg class="h-6 w-6 text-red-600 dark:text-red-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" />
            </svg>
        </Icon>
        <ChildContent>
            <p class="text-sm text-gray-500 dark:text-gray-400 mb-3">
                @string.Format(DeleteLocalizer["DeleteItemDescription"].Value, Config.TrashRetentionDays)
            </p>
            <div class="bg-gray-50 dark:bg-gray-700/50 rounded-md p-3">
                <p class="text-sm font-medium text-gray-900 dark:text-white break-all">@(Item?.Name ?? string.Empty)</p>
            </div>
        </ChildContent>
    </FormModal>
}

@code {
    private IStringLocalizer Localizer => LocalizerFactory.Create("Pages.Main.Items.View", "AliasVault.Client");
    private IStringLocalizer DeleteLocalizer => LocalizerFactory.Create("Pages.Main.Items.Delete", "AliasVault.Client");

    /// <summary>
    /// Gets or sets the item ID.
    /// </summary>
    [Parameter]
    public Guid Id { get; set; }

    private bool IsLoading { get; set; } = true;
    private Item? Item { get; set; } = new();
    private Folder? Folder { get; set; }
    private Dictionary<FieldCategory, List<DisplayField>> GroupedFields { get; set; } = new();
    private List<string> UrlValues { get; set; } = new();
    private bool ShowDeleteModal { get; set; }
    private bool IsDeleting { get; set; }

    /// <inheritdoc />
    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        // Reload the item after a full vault reload from the server so changes made on other devices
        // appear without a hard page refresh.
        DbService.GetState().StateChanged += OnVaultStateChanged;

        // Breadcrumb items are added dynamically in LoadEntryAsync after folder is loaded
    }

    /// <summary>
    /// Tracks the previous database status so we can detect a completed vault reload (Loading -> Ready).
    /// </summary>
    private DbServiceState.DatabaseStatus _lastVaultStatus = DbServiceState.DatabaseStatus.Uninitialized;

    /// <summary>
    /// Reloads the item when the vault finishes reloading from the server. The vault reload swaps in a
    /// fresh DbContext, so <see cref="LoadEntryAsync"/> re-queries and picks up any newly synced data.
    /// </summary>
    private async void OnVaultStateChanged(object? sender, DbServiceState.DatabaseState newState)
    {
        if (newState.Status == DbServiceState.DatabaseStatus.Ready && _lastVaultStatus == DbServiceState.DatabaseStatus.Loading)
        {
            await InvokeAsync(LoadEntryAsync);
        }

        _lastVaultStatus = newState.Status;
    }

    /// <inheritdoc />
    protected override async Task OnParametersSetAsync()
    {
        await base.OnParametersSetAsync();
        await LoadEntryAsync();
    }

    /// <summary>
    /// Loads the item.
    /// </summary>
    private async Task LoadEntryAsync()
    {
        IsLoading = true;
        StateHasChanged();

        // Load the item from the database via ItemService.
        Item = await ItemService.LoadEntryAsync(Id);

        if (Item is null)
        {
            // Error loading item.
            GlobalNotificationService.AddErrorMessage(Localizer["ItemNotFoundError"]);
            NavigationManager.NavigateTo("/items", false, true);
            return;
        }

        // Load the folder if the item is in one
        Folder = null;
        if (Item.FolderId.HasValue)
        {
            Folder = await FolderService.GetByIdAsync(Item.FolderId.Value);
        }

        // Add breadcrumb items - Home is already added by MainBase, add folder hierarchy if present
        if (Item.FolderId.HasValue)
        {
            await BuildFolderBreadcrumbsAsync(Item.FolderId.Value);
        }

        BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = Localizer["ViewItemBreadcrumb"] });

        // Group fields by category for display
        GroupedFields = FieldGrouper.GroupByCategory(Item);

        // Get URL values for prominent display
        UrlValues = FieldGrouper.GetUrlValues(Item);

        IsLoading = false;
        StateHasChanged();
    }

    /// <summary>
    /// Gets the email address from the item.
    /// </summary>
    private string? GetEmailAddress()
    {
        return ItemService.GetFieldValue(Item!, FieldKey.LoginEmail);
    }

    /// <summary>
    /// Gets the card number from the item (for icon display).
    /// </summary>
    private string? GetCardNumber()
    {
        return ItemService.GetFieldValue(Item!, FieldKey.CardNumber);
    }

    /// <inheritdoc />
    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        DbService.GetState().StateChanged -= OnVaultStateChanged;
        await KeyboardShortcutService.UnregisterShortcutAsync("ge");
        await KeyboardShortcutService.UnregisterShortcutAsync("gd");
    }

    /// <inheritdoc />
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);

        if (firstRender)
        {
            await KeyboardShortcutService.RegisterShortcutAsync("ge", NavigateToEdit);
            await KeyboardShortcutService.RegisterShortcutAsync("gd", OpenDeleteModal);
        }
    }

    /// <summary>
    /// Navigates to the edit page.
    /// </summary>
    private Task NavigateToEdit()
    {
        NavigationManager.NavigateTo($"/items/{Id}/edit");
        return Task.CompletedTask;
    }

    /// <summary>
    /// Opens the delete confirmation modal.
    /// </summary>
    private Task OpenDeleteModal()
    {
        ShowDeleteModal = true;
        StateHasChanged();
        return Task.CompletedTask;
    }

    /// <summary>
    /// Closes the delete confirmation modal without deleting.
    /// </summary>
    private void CancelDelete()
    {
        if (IsDeleting)
        {
            return;
        }

        ShowDeleteModal = false;
    }

    /// <summary>
    /// Confirms deletion of the current item, trashes it, and navigates back to the item list.
    /// </summary>
    private async Task ConfirmDelete()
    {
        if (IsDeleting)
        {
            return;
        }

        if (Item is null)
        {
            GlobalNotificationService.AddErrorMessage(DeleteLocalizer["DeleteItemNotFoundError"], true);
            ShowDeleteModal = false;
            return;
        }

        IsDeleting = true;
        StateHasChanged();

        try
        {
            await ItemService.TrashItemInBackgroundAsync(Id);
            GlobalNotificationService.AddSuccessMessage(DeleteLocalizer["DeleteSuccessMessage"]);
            NavigationManager.NavigateTo("/items");
        }
        finally
        {
            IsDeleting = false;
            ShowDeleteModal = false;
        }
    }
}
