using System.Text.Json;

namespace SilverOS.Welcome.Core.Apps;

public sealed record LoadedCatalog(IReadOnlyList<AppCatalogEntry> All)
{
    // Essentials (offered to all roles) first, then the role's own apps. Stable, de-duped by id.
    public IReadOnlyList<AppCatalogEntry> AppsForRole(string role) =>
        All.Where(a => a.Roles.Contains("essentials") || a.Roles.Contains(role))
           .GroupBy(a => a.Id).Select(g => g.First())
           .OrderByDescending(a => a.Group == "essentials").ThenBy(a => a.Name).ToList();

    public IReadOnlyList<string> DefaultSelectionForRole(string role) =>
        AppsForRole(role).Where(a => a.DefaultFor.Contains("essentials") || a.DefaultFor.Contains(role))
                         .Select(a => a.Id).ToList();
}

public sealed class AppCatalog : IAppCatalog
{
    private sealed record CatalogFile(int SchemaVersion, IReadOnlyList<AppCatalogEntry>? Apps);

    public LoadedCatalog Load(string directory)
    {
        var path = Path.Combine(directory, "catalog.json");
        if (!File.Exists(path)) return new LoadedCatalog(Array.Empty<AppCatalogEntry>());
        try
        {
            var f = JsonSerializer.Deserialize<CatalogFile>(File.ReadAllText(path), AppCatalogEntry.JsonOptions);
            return new LoadedCatalog(f?.Apps ?? Array.Empty<AppCatalogEntry>());
        }
        catch (JsonException)
        {
            // A bad catalog must never block onboarding — degrade to "no extra apps".
            return new LoadedCatalog(Array.Empty<AppCatalogEntry>());
        }
    }
}
