@page "/email-storage-stats"
@inherits MainBase
@using AliasVault.Admin.Services
@using AliasVault.RazorComponents
@using AliasVault.RazorComponents.Tables
@using Microsoft.EntityFrameworkCore
@inject StatisticsService StatisticsService
@inject IAliasServerDbContextFactory ContextFactory
@implements IDisposable

<PageHeader Title="Email Storage Stats" BreadcrumbItems="BreadcrumbItems">
    <CustomActions>
        <RefreshButton OnClick="RefreshData" ButtonText="Refresh" />
    </CustomActions>
</PageHeader>

<div class="px-4 space-y-6">
    <!-- Overview Statistics Cards -->
    @if (LoadingStats)
    {
        <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
            @for (int i = 0; i < 3; i++)
            {
                <div class="p-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
                    <div class="flex items-center">
                        <div class="ml-4">
                            <div class="w-32 h-4 bg-gray-200 dark:bg-gray-700 rounded animate-pulse mb-2"></div>
                            <div class="w-16 h-6 bg-gray-200 dark:bg-gray-700 rounded animate-pulse"></div>
                        </div>
                    </div>
                </div>
            }
        </div>
    }
    else
    {
        <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
            <div class="p-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
                <div class="flex items-center">
                    <div class="ml-4">
                        <h3 class="text-lg font-semibold text-gray-900 dark:text-white">Total Emails</h3>
                        <p class="text-2xl font-bold text-gray-900 dark:text-white">@TotalEmails.ToString("N0")</p>
                    </div>
                </div>
            </div>

            <div class="p-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
                <div class="flex items-center">
                    <div class="ml-4">
                        <h3 class="text-lg font-semibold text-gray-900 dark:text-white">Email Attachments</h3>
                        <p class="text-2xl font-bold text-gray-900 dark:text-white">@TotalAttachments.ToString("N0")</p>
                    </div>
                </div>
            </div>

            <div class="p-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
                <div class="flex items-center">
                    <div class="ml-4">
                        <h3 class="text-lg font-semibold text-gray-900 dark:text-white">Storage Used</h3>
                        <p class="text-2xl font-bold text-gray-900 dark:text-white">@TotalStorageMB.ToString("N2") MB</p>
                    </div>
                </div>
            </div>
        </div>
    }

    <!-- Email Attachments Table -->
    <div class="p-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800">
        <div class="flex items-center justify-between mb-4">
            <div>
                <h3 class="text-lg font-semibold text-gray-900 dark:text-white">Email Attachments</h3>
                <p class="text-sm text-gray-500 dark:text-gray-400">All email attachments stored in the system. The content of the attachments is encrypted with the user's public key and are unreadable by the server.</p>
            </div>
        </div>

    @if (LoadingAttachments)
    {
        <div class="p-4">
            <div class="animate-pulse">
                @for (int i = 0; i < 5; i++)
                {
                    <div class="flex items-center justify-between py-3 border-b border-gray-200 dark:border-gray-700">
                        <div class="flex items-center space-x-3">
                            <div class="w-8 h-4 bg-gray-200 dark:bg-gray-700 rounded"></div>
                            <div class="w-32 h-4 bg-gray-200 dark:bg-gray-700 rounded"></div>
                            <div class="w-16 h-4 bg-gray-200 dark:bg-gray-700 rounded"></div>
                            <div class="w-24 h-4 bg-gray-200 dark:bg-gray-700 rounded"></div>
                        </div>
                        <div class="w-16 h-8 bg-gray-200 dark:bg-gray-700 rounded"></div>
                    </div>
                }
            </div>
        </div>
    }
    else if (Attachments?.Any() == true)
    {
        <div class="overflow-x-auto">
            <SortableTable Columns="@_tableColumns" SortColumn="@SortColumn" SortDirection="@SortDirection" OnSortChanged="HandleSortChanged">
                @foreach (var attachment in Attachments)
                {
                    <SortableTableRow>
                        <SortableTableColumn IsPrimary="true">@attachment.Id</SortableTableColumn>
                        <SortableTableColumn>
                            <span class="font-medium text-gray-900 dark:text-white">@attachment.Filename</span>
                            <div class="text-sm text-gray-500 dark:text-gray-400">@attachment.MimeType</div>
                        </SortableTableColumn>
                        <SortableTableColumn>@FormatFileSize(attachment.Filesize)</SortableTableColumn>
                        <SortableTableColumn>
                            <span>@attachment.EmailId</span>
                        </SortableTableColumn>
                        <SortableTableColumn>
                            @if (!string.IsNullOrEmpty(attachment.UserEmail))
                            {
                                <a href="users/@attachment.UserId">
                                    @attachment.UserEmail
                                </a>
                            }
                            else
                            {
                                <span>Unknown</span>
                            }
                        </SortableTableColumn>
                        <SortableTableColumn>
                            <button @onclick="() => DeleteAttachment(attachment.Id)"
                                    class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300 text-sm font-medium">
                                Delete
                            </button>
                        </SortableTableColumn>
                    </SortableTableRow>
                }
            </SortableTable>
        </div>

        <div class="px-6 py-3 border-t border-gray-200 dark:border-gray-700">
            <Paginator CurrentPage="CurrentPage"
                      PageSize="20"
                      TotalRecords="TotalRecords"
                      OnPageChanged="HandlePageChanged" />
        </div>
    }
    else
    {
        <div class="p-8 text-center">
            <div class="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-gray-100 dark:bg-gray-700">
                <svg class="h-6 w-6 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z"/>
                </svg>
            </div>
            <h3 class="mt-2 text-sm font-medium text-gray-900 dark:text-white">No attachments found</h3>
            <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">No email attachments exist in the system.</p>
        </div>
    }
    </div>

    @if (ErrorMessage != null)
    {
        <div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4">
            <div class="flex">
                <div class="flex-shrink-0">
                    <svg class="h-5 w-5 text-red-400" fill="currentColor" viewBox="0 0 20 20">
                        <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
                    </svg>
                </div>
                <div class="ml-3">
                    <h3 class="text-sm font-medium text-red-800 dark:text-red-200">Error Loading Data</h3>
                    <p class="text-sm text-red-700 dark:text-red-300 mt-1">@ErrorMessage</p>
                </div>
            </div>
        </div>
    }
</div>

@code {
    private bool LoadingStats = true;
    private bool LoadingAttachments = true;
    private string? ErrorMessage;
    private bool _disposed = false;

    private int TotalEmails = 0;
    private int TotalAttachments = 0;
    private double TotalStorageMB = 0;

    private List<EmailAttachmentModel>? Attachments;
    private int CurrentPage = 1;
    private int TotalRecords = 0;

    private string SortColumn { get; set; } = "Filesize";
    private SortDirection SortDirection { get; set; } = SortDirection.Descending;

    private readonly List<TableColumn> _tableColumns = [
        new TableColumn { Title = "ID", PropertyName = "Id" },
        new TableColumn { Title = "Filename", PropertyName = "Filename" },
        new TableColumn { Title = "File Size", PropertyName = "Filesize" },
        new TableColumn { Title = "Email ID", PropertyName = "EmailId" },
        new TableColumn { Title = "User", PropertyName = "UserEmail" },
        new TableColumn { Title = "Actions", Sortable = false },
    ];

    public class EmailAttachmentModel
    {
        public int Id { get; set; }
        public string Filename { get; set; } = string.Empty;
        public string MimeType { get; set; } = string.Empty;
        public int Filesize { get; set; }
        public int EmailId { get; set; }
        public string? UserId { get; set; }
        public string? UserEmail { get; set; }
    }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = "Emails", Url = "emails" });
        BreadcrumbItems.Add(new BreadcrumbItem { DisplayName = "Email Storage Stats" });

        await RefreshData();
    }

    private void SafeStateHasChanged()
    {
        if (!_disposed)
        {
            InvokeAsync(StateHasChanged);
        }
    }

    private async Task RefreshData()
    {
        if (_disposed) return;

        LoadingStats = true;
        LoadingAttachments = true;
        ErrorMessage = null;
        SafeStateHasChanged();

        try
        {
            await using var context = await ContextFactory.CreateDbContextAsync();

            // Load statistics
            TotalEmails = await context.Emails.CountAsync();
            TotalAttachments = await context.EmailAttachments.CountAsync();

            var totalBytes = TotalAttachments > 0
                ? await context.EmailAttachments.SumAsync(a => (long)a.Filesize)
                : 0L;
            TotalStorageMB = totalBytes / (1024.0 * 1024.0);

            LoadingStats = false;
            SafeStateHasChanged();

            // Load attachments
            await LoadAttachments();
        }
        catch (Exception ex)
        {
            if (!_disposed)
            {
                ErrorMessage = $"Error loading data: {ex.Message}";
                LoadingStats = false;
                LoadingAttachments = false;
                SafeStateHasChanged();
            }
        }
    }

    private async Task LoadAttachments()
    {
        if (_disposed) return;

        LoadingAttachments = true;
        SafeStateHasChanged();

        try
        {
            await using var context = await ContextFactory.CreateDbContextAsync();

            TotalRecords = await context.EmailAttachments.CountAsync();

            var skip = (CurrentPage - 1) * 20;

            // Apply sorting and pagination
            var sortedQuery = ApplySort(context.EmailAttachments);

            var attachmentData = await sortedQuery
                .Skip(skip)
                .Take(20)
                .ToListAsync();

            // Then map to view models to avoid disposed context issues
            if (!_disposed)
            {
                Attachments = attachmentData.Select(a => new EmailAttachmentModel
                {
                    Id = a.Id,
                    Filename = a.Filename,
                    MimeType = a.MimeType,
                    Filesize = a.Filesize,
                    EmailId = a.EmailId,
                    UserId = a.Email?.EncryptionKey?.UserId,
                    UserEmail = a.Email?.EncryptionKey?.User?.UserName
                }).ToList();
            }
        }
        catch (Exception ex)
        {
            if (!_disposed)
            {
                ErrorMessage = $"Error loading attachments: {ex.Message}";
            }
        }
        finally
        {
            if (!_disposed)
            {
                LoadingAttachments = false;
                SafeStateHasChanged();
            }
        }
    }

    private async Task HandlePageChanged(int newPage)
    {
        CurrentPage = newPage;
        await LoadAttachments();
    }

    private async Task HandleSortChanged((string column, SortDirection direction) sort)
    {
        SortColumn = sort.column;
        SortDirection = sort.direction;
        CurrentPage = 1; // Reset to first page when sorting changes
        await LoadAttachments();
    }

    private IQueryable<EmailAttachment> ApplySort(IQueryable<EmailAttachment> query)
    {
        // Always include navigation properties for all sorting scenarios
        query = query.Include(a => a.Email)
            .ThenInclude(e => e.EncryptionKey)
            .ThenInclude(k => k.User);

        switch (SortColumn)
        {
            case "Id":
                query = SortDirection == SortDirection.Ascending
                    ? query.OrderBy(x => x.Id)
                    : query.OrderByDescending(x => x.Id);
                break;
            case "Filename":
                query = SortDirection == SortDirection.Ascending
                    ? query.OrderBy(x => x.Filename)
                    : query.OrderByDescending(x => x.Filename);
                break;
            case "Filesize":
                query = SortDirection == SortDirection.Ascending
                    ? query.OrderBy(x => x.Filesize)
                    : query.OrderByDescending(x => x.Filesize);
                break;
            case "EmailId":
                query = SortDirection == SortDirection.Ascending
                    ? query.OrderBy(x => x.EmailId)
                    : query.OrderByDescending(x => x.EmailId);
                break;
            case "UserEmail":
                query = SortDirection == SortDirection.Ascending
                    ? query.OrderBy(x => x.Email.EncryptionKey.User.Email)
                    : query.OrderByDescending(x => x.Email.EncryptionKey.User.Email);
                break;
            default:
                query = query.OrderByDescending(x => x.Filesize);
                break;
        }

        return query;
    }

    private async Task DeleteAttachment(int attachmentId)
    {
        var confirmed = await ConfirmModalService.ShowConfirmation(
            "Delete Attachment",
            "Are you sure you want to delete this attachment? This action cannot be undone.",
            "Delete",
            "Cancel");

        if (!confirmed) return;

        try
        {
            await using var context = await ContextFactory.CreateDbContextAsync();

            var attachment = await context.EmailAttachments.FindAsync(attachmentId);
            if (attachment != null)
            {
                context.EmailAttachments.Remove(attachment);
                await context.SaveChangesAsync();

                // Refresh data after deletion
                await RefreshData();
            }
        }
        catch (Exception ex)
        {
            if (!_disposed)
            {
                ErrorMessage = $"Error deleting attachment: {ex.Message}";
                SafeStateHasChanged();
            }
        }
    }

    private static string FormatFileSize(int bytes)
    {
        if (bytes < 1024)
            return $"{bytes} B";
        else if (bytes < 1024 * 1024)
            return $"{bytes / 1024.0:F1} KB";
        else
            return $"{bytes / (1024.0 * 1024.0):F1} MB";
    }

    public void Dispose()
    {
        _disposed = true;
    }
}