using System.Windows;
using Microsoft.Win32;
using Microsoft.Extensions.Logging;

namespace SharepointToolbox.Services;

public enum ThemeMode { System, Light, Dark }

/// <summary>
/// Swaps the merged palette dictionary at runtime so all DynamicResource brush lookups retint live.
/// "System" mode reads HKCU AppsUseLightTheme (0 = dark, 1 = light) and subscribes to system theme changes.
/// </summary>
public class ThemeManager
{
    private const string LightPaletteSource = "pack://application:,,,/Themes/LightPalette.xaml";
    private const string DarkPaletteSource  = "pack://application:,,,/Themes/DarkPalette.xaml";
    private const string PersonalizeKey = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";

    private readonly ILogger<ThemeManager> _logger;
    private ThemeMode _mode = ThemeMode.System;
    private bool _systemSubscribed;

    public event EventHandler? ThemeChanged;

    public ThemeMode Mode => _mode;
    public bool IsDarkActive { get; private set; }

    public ThemeManager(ILogger<ThemeManager> logger)
    {
        _logger = logger;
    }

    public void ApplyMode(ThemeMode mode)
    {
        _mode = mode;
        bool dark = ResolveDark(mode);
        ApplyPalette(dark);
        EnsureSystemSubscription(mode);
    }

    public void ApplyFromString(string? value)
    {
        var mode = (value ?? "System") switch
        {
            "Light" => ThemeMode.Light,
            "Dark"  => ThemeMode.Dark,
            _        => ThemeMode.System,
        };
        ApplyMode(mode);
    }

    private bool ResolveDark(ThemeMode mode) => mode switch
    {
        ThemeMode.Light => false,
        ThemeMode.Dark  => true,
        _               => ReadSystemPrefersDark(),
    };

    private bool ReadSystemPrefersDark()
    {
        try
        {
            using var key = Registry.CurrentUser.OpenSubKey(PersonalizeKey);
            if (key?.GetValue("AppsUseLightTheme") is int v)
                return v == 0;
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to read system theme preference, defaulting to light");
        }
        return false;
    }

    private void ApplyPalette(bool dark)
    {
        var app = Application.Current;
        if (app is null) return;

        var newPalette = new ResourceDictionary
        {
            Source = new Uri(dark ? DarkPaletteSource : LightPaletteSource, UriKind.Absolute)
        };

        var dicts = app.Resources.MergedDictionaries;
        int replaced = -1;
        for (int i = 0; i < dicts.Count; i++)
        {
            var src = dicts[i].Source?.OriginalString ?? string.Empty;
            if (src.EndsWith("LightPalette.xaml", StringComparison.OrdinalIgnoreCase) ||
                src.EndsWith("DarkPalette.xaml",  StringComparison.OrdinalIgnoreCase))
            {
                replaced = i;
                break;
            }
        }

        if (replaced >= 0)
            dicts[replaced] = newPalette;
        else
            dicts.Insert(0, newPalette);

        IsDarkActive = dark;
        ThemeChanged?.Invoke(this, EventArgs.Empty);
    }

    private void EnsureSystemSubscription(ThemeMode mode)
    {
        if (mode == ThemeMode.System && !_systemSubscribed)
        {
            SystemEvents.UserPreferenceChanged += OnUserPreferenceChanged;
            _systemSubscribed = true;
        }
        else if (mode != ThemeMode.System && _systemSubscribed)
        {
            SystemEvents.UserPreferenceChanged -= OnUserPreferenceChanged;
            _systemSubscribed = false;
        }
    }

    private void OnUserPreferenceChanged(object? sender, UserPreferenceChangedEventArgs e)
    {
        if (e.Category != UserPreferenceCategory.General) return;
        if (_mode != ThemeMode.System) return;

        var app = Application.Current;
        if (app is null) return;

        app.Dispatcher.BeginInvoke(new Action(() =>
        {
            bool dark = ReadSystemPrefersDark();
            if (dark != IsDarkActive)
                ApplyPalette(dark);
        }));
    }
}
