using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Styling;
using PolyTraderSharp.Models;
using PolyTraderSharp.Services;

namespace PolyTrader.App.Avalonia.Shell
{
    /// <summary>
    /// Verwaltet das Farbschema (hell/dunkel/System) und macht es persistent.
    ///
    /// <para>Die Standard-Steuerelemente stellt Avalonia selbst um, sobald
    /// <see cref="global::Avalonia.Application.RequestedThemeVariant"/> wechselt – für alles, was per
    /// <c>DynamicResource</c> gebunden ist, gilt dasselbe. Farben, die im Code gesetzt werden
    /// (Zeilenhintergründe, Umschalter-Flächen, KPI-Vorzeichen), aktualisieren sich dagegen NICHT von
    /// selbst. Fenster mit solchen Stellen hängen sich deshalb an <see cref="ThemeChanged"/> und
    /// zeichnen sie dort neu.</para>
    /// </summary>
    public static class ThemeManager
    {
        private static ServerSettings? _settings;
        private static string? _settingsPath;
        private static TerminalLogger? _logger;

        /// <summary>Feuert nach jedem Wechsel – Fenster zeichnen daraufhin ihre Code-Farben neu.</summary>
        public static event Action? ThemeChanged;

        /// <summary>Ist gerade das dunkle Schema aktiv (auch wenn es über „System" kam)?</summary>
        public static bool IsDark =>
            global::Avalonia.Application.Current?.ActualThemeVariant == ThemeVariant.Dark;

        /// <summary>
        /// Einmalig beim Start aufrufen: übernimmt das gespeicherte Schema und merkt sich, wohin
        /// spätere Änderungen geschrieben werden.
        /// </summary>
        public static void Initialize(ServerSettings settings, string settingsPath, TerminalLogger? logger = null)
        {
            _settings = settings;
            _settingsPath = settingsPath;
            _logger = logger;
            ApplyVariant(settings.Theme);
        }

        /// <summary>Wechselt hell ↔ dunkel und speichert die Wahl. „System" wird dabei zu einer festen Wahl.</summary>
        public static void Toggle()
        {
            Set(IsDark ? AppThemeVariant.Hell : AppThemeVariant.Dunkel);
        }

        /// <summary>Setzt das Schema, speichert es und benachrichtigt die Fenster.</summary>
        public static void Set(AppThemeVariant variant)
        {
            ApplyVariant(variant);

            if (_settings != null && _settingsPath != null)
            {
                _settings.Theme = variant;
                try
                {
                    _settings.Save(_settingsPath);
                }
                catch (Exception ex)
                {
                    // Ein fehlgeschlagenes Speichern darf die Umschaltung nicht verhindern –
                    // sie gilt dann nur für diese Sitzung.
                    _logger?.Warning($"Farbschema konnte nicht gespeichert werden: {ex.Message}");
                }
            }

            ThemeChanged?.Invoke();
        }

        private static void ApplyVariant(AppThemeVariant variant)
        {
            var app = global::Avalonia.Application.Current;
            if (app == null) return;

            app.RequestedThemeVariant = variant switch
            {
                AppThemeVariant.Hell => ThemeVariant.Light,
                AppThemeVariant.Dunkel => ThemeVariant.Dark,
                _ => ThemeVariant.Default   // folgt dem Betriebssystem
            };
        }

        /// <summary>
        /// Löst eine Farbe aus den Themen-Ressourcen auf. Für Stellen, die ihre Farbe im Code setzen
        /// müssen (Grid-Zeilen, Umschalter) – im XAML nimmt man stattdessen <c>DynamicResource</c>.
        /// </summary>
        public static IBrush Brush(string key)
        {
            var app = global::Avalonia.Application.Current;
            if (app != null && app.TryFindResource(key, app.ActualThemeVariant, out object? value) && value is IBrush b)
                return b;

            // Unbekannter Schlüssel ist ein Programmierfehler, darf die Oberfläche aber nicht kippen.
            return Brushes.Gray;
        }
    }
}
