@using AliasVault.RazorComponents.Tables

<SortableTable Columns="@_vaultTableColumns" SortColumn="@SortColumn" SortDirection="@SortDirection" OnSortChanged="HandleSortChanged">
    @foreach (var entry in SortedVaultList)
    {
        <SortableTableRow>
            <SortableTableColumn IsPrimary="true">@entry.Id</SortableTableColumn>
            <SortableTableColumn>@entry.CreatedAt.ToString("yyyy-MM-dd HH:mm")</SortableTableColumn>
            <SortableTableColumn>@entry.UpdatedAt.ToString("yyyy-MM-dd HH:mm")</SortableTableColumn>
            <SortableTableColumn>@Math.Round((double)entry.FileSize / 1024, 1) MB</SortableTableColumn>
            <SortableTableColumn>@entry.Version</SortableTableColumn>
            <SortableTableColumn>@entry.Client</SortableTableColumn>
            <SortableTableColumn>@entry.RevisionNumber</SortableTableColumn>
            <SortableTableColumn>@entry.CredentialsCount</SortableTableColumn>
            <SortableTableColumn>@entry.EmailClaimsCount</SortableTableColumn>
            <SortableTableColumn>
                @if (entry == LatestVault)
                {
                    <span class="bg-blue-100 text-blue-800 text-xs font-medium mr-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300">Current</span>
                }
                @if (_previousEntry != null && HasPasswordChanged(entry, SortedVaultList))
                {
                    <span class="bg-green-100 text-green-800 text-xs font-medium mr-2 px-2.5 py-0.5 rounded dark:bg-green-900 dark:text-green-300">Password Changed</span>
                }
            </SortableTableColumn>
            <SortableTableColumn>
                @if (entry != LatestVault)
                {
                    <Button OnClick="() => MakeCurrentAsync(entry)">Restore</Button>
                }
            </SortableTableColumn>
        </SortableTableRow>
        _previousEntry = entry;
    }
</SortableTable>

@code {
    /// <summary>
    /// Gets or sets the list of vaults to display.
    /// </summary>
    [Parameter]
    public List<Vault> VaultList { get; set; } = [];

    /// <summary>
    /// Gets or sets the event callback to make a vault current.
    /// </summary>
    [Parameter]
    public EventCallback<Vault> OnMakeCurrent { get; set; }

    private string SortColumn { get; set; } = "RevisionNumber";
    private SortDirection SortDirection { get; set; } = SortDirection.Descending;
    private Vault? _previousEntry;

    private readonly List<TableColumn> _vaultTableColumns = [
        new TableColumn { Title = "ID", PropertyName = "Id" },
        new TableColumn { Title = "Created", PropertyName = "CreatedAt" },
        new TableColumn { Title = "Updated", PropertyName = "UpdatedAt" },
        new TableColumn { Title = "Filesize", PropertyName = "FileSize" },
        new TableColumn { Title = "DB version", PropertyName = "Version" },
        new TableColumn { Title = "Client", PropertyName = "Client" },
        new TableColumn { Title = "Revision", PropertyName = "RevisionNumber" },
        new TableColumn { Title = "Credentials", PropertyName = "CredentialsCount" },
        new TableColumn { Title = "Email Claims", PropertyName = "EmailClaimsCount" },
        new TableColumn { Title = "Status", Sortable = false },
        new TableColumn { Title = "Actions", Sortable = false },
    ];

    private IEnumerable<Vault> SortedVaultList => SortList(VaultList, SortColumn, SortDirection);

    private Vault? LatestVault => VaultList.MaxBy(v => v.RevisionNumber);

    private void HandleSortChanged((string column, SortDirection direction) sort)
    {
        SortColumn = sort.column;
        SortDirection = sort.direction;
        StateHasChanged();
    }

    private static IEnumerable<Vault> SortList(List<Vault> vaults, string sortColumn, SortDirection sortDirection)
    {
        return sortColumn switch
        {
            "Id" => SortableTable.SortListByProperty(vaults, v => v.Id, sortDirection),
            "CreatedAt" => SortableTable.SortListByProperty(vaults, v => v.CreatedAt, sortDirection),
            "UpdatedAt" => SortableTable.SortListByProperty(vaults, v => v.UpdatedAt, sortDirection),
            "FileSize" => SortableTable.SortListByProperty(vaults, v => v.FileSize, sortDirection),
            "Version" => SortableTable.SortListByProperty(vaults, v => v.Version, sortDirection),
            "Client" => SortableTable.SortListByProperty(vaults, v => v.Client, sortDirection),
            "RevisionNumber" => SortableTable.SortListByProperty(vaults, v => v.RevisionNumber, sortDirection),
            "CredentialsCount" => SortableTable.SortListByProperty(vaults, v => v.CredentialsCount, sortDirection),
            "EmailClaimsCount" => SortableTable.SortListByProperty(vaults, v => v.EmailClaimsCount, sortDirection),
            _ => vaults
        };
    }

    /// <summary>
    /// Checks if the password has changed between the current and previous vault entry based on revision number..
    /// </summary>
    private static bool HasPasswordChanged(Vault current, IEnumerable<Vault> vaultList)
    {
        // Get the previous vault entry to compare to based on revision number.
        var previousEntry = vaultList.FirstOrDefault(v => v.RevisionNumber == current.RevisionNumber - 1);

        if (previousEntry == null)
        {
            // If the previous entry is null it means we have nothing to compare to so assume that it has not changed.
            return false;
        }

        return current.Salt != previousEntry.Salt || current.Verifier != previousEntry.Verifier;
    }

    private async Task MakeCurrentAsync(Vault vault)
    {
        await OnMakeCurrent.InvokeAsync(vault);
    }
}
