using System.IO;
using System.Text.Json;

namespace NexusShell.Services.Policy;

public sealed class NexusPolicyStore
{
    private readonly string _policiesDir;
    private readonly string _seedDir;
    private readonly Dictionary<NexusRole, NexusRolePolicy> _rolePolicies = new();

    public NexusPolicyStore()
    {
        _policiesDir = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
            "NinjaNexus",
            "policies");
        _seedDir = Path.Combine(AppContext.BaseDirectory, "Assets", "Policies");
        Directory.CreateDirectory(_policiesDir);
        SeedDefaultsIfMissing();
        LoadAll();
    }

    public string PoliciesDirectory => _policiesDir;

    public IReadOnlyDictionary<NexusRole, NexusRolePolicy> RolePolicies => _rolePolicies;

    public NexusRolePolicy? GetForRole(NexusRole role) =>
        _rolePolicies.TryGetValue(role, out var policy) ? policy : null;

    public NexusRolePolicy GetForRoleOrDefault(NexusRole role) =>
        GetForRole(role) ?? GetForRole(NexusRole.User)!;

    public void Save(NexusPolicy policy)
    {
        var fileName = $"{policy.Id}.json";
        var path = Path.Combine(_policiesDir, fileName);
        var json = JsonSerializer.Serialize(policy, WriteOptions);
        File.WriteAllText(path, json);
        _rolePolicies[policy.ParsedRole] = NexusRolePolicy.FromPolicy(policy, path);
    }

    public void Reload()
    {
        _rolePolicies.Clear();
        LoadAll();
    }

    private void LoadAll()
    {
        foreach (var file in Directory.EnumerateFiles(_policiesDir, "*.json"))
        {
            try
            {
                var json = File.ReadAllText(file);
                var policy = JsonSerializer.Deserialize<NexusPolicy>(json, ReadOptions);
                if (policy is null || string.IsNullOrWhiteSpace(policy.Role))
                {
                    continue;
                }

                _rolePolicies[policy.ParsedRole] = NexusRolePolicy.FromPolicy(policy, file);
            }
            catch
            {
                // POC: skip invalid policy files
            }
        }
    }

    private void SeedDefaultsIfMissing()
    {
        if (!Directory.Exists(_seedDir))
        {
            return;
        }

        foreach (var seedFile in Directory.EnumerateFiles(_seedDir, "default-*.json"))
        {
            var dest = Path.Combine(_policiesDir, Path.GetFileName(seedFile));
            if (!File.Exists(dest))
            {
                File.Copy(seedFile, dest);
            }
        }
    }

    private static readonly JsonSerializerOptions ReadOptions = new()
    {
        PropertyNameCaseInsensitive = true,
        ReadCommentHandling = JsonCommentHandling.Skip,
        AllowTrailingCommas = true,
    };

    private static readonly JsonSerializerOptions WriteOptions = new()
    {
        WriteIndented = true,
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    };
}
