using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace RioJoy.Core.Profiles;

/// <summary>
/// Loads and saves <see cref="AppConfig"/> as JSON. Replaces the legacy
/// SimpleIni single-file config with a profile library (see docs/PLAN.md).
/// Newtonsoft rather than System.Text.Json so the net40 (Windows XP) flavor
/// shares one serializer — and one on-disk format — with net48 (PLAN.md §8A).
/// Conventions match the original STJ settings: indented, PascalCase names,
/// enums as strings, nulls skipped — existing config.json files parse as-is.
/// </summary>
public static class ConfigStore
{
    private static readonly JsonSerializerSettings Options = new()
    {
        Formatting = Formatting.Indented,
        NullValueHandling = NullValueHandling.Ignore,
        Converters = { new StringEnumConverter() },
    };

    public static string Serialize(AppConfig config)
    {
        if (config is null) throw new ArgumentNullException(nameof(config));
        return JsonConvert.SerializeObject(config, Options);
    }

    public static AppConfig Deserialize(string json)
    {
        if (string.IsNullOrWhiteSpace(json)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(json));
        return JsonConvert.DeserializeObject<AppConfig>(json, Options)
               ?? throw new JsonSerializationException("Config JSON deserialized to null.");
    }

    /// <summary>Save the config to <paramref name="path"/> (creating directories).</summary>
    public static void Save(AppConfig config, string path)
    {
        if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(path));
        string? dir = Path.GetDirectoryName(Path.GetFullPath(path));
        if (!string.IsNullOrEmpty(dir))
            Directory.CreateDirectory(dir);
        File.WriteAllText(path, Serialize(config));
    }

    /// <summary>
    /// Load the config from <paramref name="path"/>, or return a fresh default
    /// <see cref="AppConfig"/> if the file does not exist.
    /// </summary>
    public static AppConfig Load(string path)
    {
        if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(path));
        return File.Exists(path) ? Deserialize(File.ReadAllText(path)) : new AppConfig();
    }
}
