using System.Text.Json;

namespace RolemasterDb.App.Frontend.AppState;

public sealed class RecentTablesState(BrowserStorageService browserStorage)
{
    private const int MaxItems = 8;
    private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web);
    private bool isInitialized;

    public IReadOnlyList<RecentTableEntry> Items { get; private set; } = [];

    public event Action? Changed;

    public async Task InitializeAsync()
    {
        if (isInitialized)
        {
            return;
        }

        try
        {
            var storedValue = await browserStorage.GetItemAsync(BrowserStorageKeys.RecentTables);
            Items = DeserializeItems(storedValue);
            isInitialized = true;
            Changed?.Invoke();
        }
        catch (JsonException)
        {
            Items = [];
            isInitialized = true;
            Changed?.Invoke();
        }
        catch (InvalidOperationException)
        {
            // JS interop is unavailable during prerender. Retry on the next interactive render.
        }
    }

    public async Task RecordVisitAsync(string slug, string label, string family, int curationPercentage)
    {
        if (string.IsNullOrWhiteSpace(slug) || string.IsNullOrWhiteSpace(label))
        {
            return;
        }

        await InitializeAsync();

        var updatedItems = new List<RecentTableEntry>
        {
            new(
                slug.Trim(),
                label.Trim(),
                family.Trim(),
                curationPercentage,
                DateTimeOffset.UtcNow)
        };

        foreach (var item in Items)
        {
            if (string.Equals(item.Slug, slug, StringComparison.OrdinalIgnoreCase))
            {
                continue;
            }

            updatedItems.Add(item);
            if (updatedItems.Count == MaxItems)
            {
                break;
            }
        }

        Items = updatedItems;
        await PersistAsync();
        Changed?.Invoke();
    }

    private async Task PersistAsync()
    {
        var serialized = JsonSerializer.Serialize(Items, SerializerOptions);
        await browserStorage.SetItemAsync(BrowserStorageKeys.RecentTables, serialized);
    }

    private static IReadOnlyList<RecentTableEntry> DeserializeItems(string? storedValue)
    {
        if (string.IsNullOrWhiteSpace(storedValue))
        {
            return [];
        }

        var items = JsonSerializer.Deserialize<List<RecentTableEntry>>(storedValue, SerializerOptions);
        if (items is null || items.Count == 0)
        {
            return [];
        }

        return items
            .Where(item => !string.IsNullOrWhiteSpace(item.Slug) && !string.IsNullOrWhiteSpace(item.Label))
            .GroupBy(item => item.Slug, StringComparer.OrdinalIgnoreCase)
            .Select(group => group
                .OrderByDescending(item => item.ViewedAtUtc)
                .First())
            .OrderByDescending(item => item.ViewedAtUtc)
            .Take(MaxItems)
            .ToList();
    }
}
