using System.Text.Json;
using Microsoft.Extensions.Logging;
using PSLauncher.Models;

namespace PSLauncher.Core.Configuration;

public sealed class ConfigStore : IConfigStore
{
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        WriteIndented = true,
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        PropertyNameCaseInsensitive = true
    };

    private readonly ILogger<ConfigStore> _logger;
    private readonly string _configFile;

    public string ConfigDirectory { get; }

    public ConfigStore(ILogger<ConfigStore> logger)
    {
        _logger = logger;
        ConfigDirectory = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
            "PSLauncher");
        Directory.CreateDirectory(ConfigDirectory);
        _configFile = Path.Combine(ConfigDirectory, "config.json");
    }

    public LocalConfig Load()
    {
        if (!File.Exists(_configFile))
        {
            var fresh = new LocalConfig
            {
                InstallRoot = ResolveDefaultInstallRoot()
            };
            Save(fresh);
            return fresh;
        }

        try
        {
            using var fs = File.OpenRead(_configFile);
            var cfg = JsonSerializer.Deserialize<LocalConfig>(fs, JsonOptions) ?? new LocalConfig();
            if (string.IsNullOrWhiteSpace(cfg.InstallRoot))
                cfg.InstallRoot = ResolveDefaultInstallRoot();
            return cfg;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to load config; using defaults");
            return new LocalConfig { InstallRoot = ResolveDefaultInstallRoot() };
        }
    }

    public void Save(LocalConfig config)
    {
        var tmp = _configFile + ".tmp";
        using (var fs = File.Create(tmp))
        {
            JsonSerializer.Serialize(fs, config, JsonOptions);
        }
        File.Move(tmp, _configFile, overwrite: true);
    }

    /// <summary>
    /// Cible standard pour les déploiements clients : <c>C:\ASTERION_VR</c>.
    /// Si un dossier ASTERION_VR existe déjà à côté de l'exe (mode dev / portable),
    /// il est préféré pour ne pas casser l'environnement de développement.
    /// </summary>
    private static string ResolveDefaultInstallRoot()
    {
        // Mode dev / portable : ASTERION_VR à côté de l'exe (par ex. dans le repo)
        var exeDir = AppContext.BaseDirectory;
        var sibling = Path.Combine(
            Path.GetDirectoryName(exeDir.TrimEnd(Path.DirectorySeparatorChar))!,
            "ASTERION_VR");
        if (Directory.Exists(sibling)) return sibling;

        // Cible standard pour les clients (créée au premier install si absente)
        return @"C:\ASTERION_VR";
    }
}
