using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using PSLauncher.Core.Localization;
using PSLauncher.Models;

namespace PSLauncher.App.Views;

/// <summary>
/// Modal d'édition d'une entrée du bandeau de santé. Présenté soit pour création
/// (constructeur sans argument), soit pour modification (constructeur avec entry
/// existante). À la sauvegarde, applique les valeurs sur l'objet d'origine pour
/// que la liste parente n'ait rien à reconstruire.
///
/// Choix UI : icon picker en grille avec 28 emojis curatés couvrant les usages
/// VR/streaming/réseau (les checks typiques de PROSERVE). On évite la saisie
/// libre d'un emoji pour ne pas se retrouver avec des caractères qui ne rendent
/// pas bien dans la pill du bandeau.
/// </summary>
public partial class HealthCheckEditorDialog : Window
{
    /// <summary>Emojis proposés dans le picker. Listés du plus probable au moins probable.</summary>
    private static readonly string[] CuratedIcons =
    {
        "🎮", "🥽", "📡", "🌐", "📶", "🔌", "💻", "🖥",
        "📷", "🎧", "🛡", "🔥", "⚙", "🚀", "🔧", "📦",
        "🎯", "🏃", "🚨", "🔋", "💾", "🔍", "📊", "🖱",
        "⌨", "🎚", "🟢", "🔵",
    };

    public HealthCheckEntry Entry { get; }
    public bool Saved { get; private set; }

    private readonly ObservableCollection<IconOption> _icons = new();

    public HealthCheckEditorDialog() : this(new HealthCheckEntry
    {
        Name = "",
        Icon = "🔌",
        Kind = "Process",
        Target = "",
        RefreshIntervalMs = 5000,
    }, isNew: true)
    {
    }

    /// <summary>Aliases acceptés par OpenVrService pour le picker VrDevice.</summary>
    private static readonly VrAliasOption[] VrAliases =
    {
        new("hmd",                 "HMD"),
        new("left_controller",     "Manette gauche"),
        new("right_controller",    "Manette droite"),
        new("tracker_1",           "Tracker #1"),
        new("tracker_2",           "Tracker #2"),
        new("tracker_3",           "Tracker #3"),
        new("base_station_1",      "Base station #1"),
        new("base_station_2",      "Base station #2"),
    };

    public HealthCheckEditorDialog(HealthCheckEntry entry, bool isNew = false)
    {
        Entry = entry;
        InitializeComponent();

        TitleText.Text = isNew ? Strings.HealthEditorTitleNew : Strings.HealthEditorTitle;

        // Charge les valeurs courantes
        NameBox.Text = entry.Name ?? "";
        TargetBox.Text = entry.Target ?? "";
        RefreshMsBox.Text = entry.RefreshIntervalMs.ToString();

        VrDeviceCombo.ItemsSource = VrAliases;

        var kind = (entry.Kind ?? "Process").Trim().ToLowerInvariant();
        var isPing     = kind == "ping";
        var isVrDevice = kind == "vrdevice";
        var isProcess  = !isPing && !isVrDevice;
        KindProcess.IsChecked  = isProcess;
        KindPing.IsChecked     = isPing;
        KindVrDevice.IsChecked = isVrDevice;

        if (isVrDevice)
        {
            // Sélectionne l'alias correspondant ; fallback "hmd" si Target inconnu
            var alias = string.IsNullOrEmpty(entry.Target) ? "hmd" : entry.Target.Trim().ToLowerInvariant();
            var match = VrAliases.FirstOrDefault(a => string.Equals(a.Alias, alias, StringComparison.OrdinalIgnoreCase));
            VrDeviceCombo.SelectedValue = match?.Alias ?? "hmd";
        }
        else
        {
            VrDeviceCombo.SelectedValue = "hmd";
        }

        UpdateKindUi(kind);

        PingWarnBox.Text = (entry.PingWarnMs ?? 50).ToString();
        PingErrorBox.Text = (entry.PingErrorMs ?? 200).ToString();
        PingTimeoutBox.Text = (entry.PingTimeoutMs ?? 1000).ToString();

        // Construit le picker, marque l'icône courante comme sélectionnée
        var current = string.IsNullOrEmpty(entry.Icon) ? "🔌" : entry.Icon;
        var iconList = CuratedIcons.ToList();
        if (!iconList.Contains(current)) iconList.Insert(0, current); // garde une icône custom si déjà en config
        foreach (var ic in iconList)
            _icons.Add(new IconOption(ic) { IsSelected = ic == current });
        IconPicker.ItemsSource = _icons;
    }

    private void UpdateKindUi(string kind)
    {
        switch (kind)
        {
            case "ping":
                TargetLabel.Text         = Strings.HealthEditorTargetPing;
                TargetHint.Text          = Strings.HealthEditorTargetPingHint;
                TargetBox.Visibility     = Visibility.Visible;
                VrDeviceCombo.Visibility = Visibility.Collapsed;
                PingAdvanced.Visibility  = Visibility.Visible;
                break;
            case "vrdevice":
                TargetLabel.Text         = Strings.HealthEditorTargetVrDevice;
                TargetHint.Text          = Strings.HealthEditorTargetVrDeviceHint;
                TargetBox.Visibility     = Visibility.Collapsed;
                VrDeviceCombo.Visibility = Visibility.Visible;
                PingAdvanced.Visibility  = Visibility.Collapsed;
                break;
            default: // process
                TargetLabel.Text         = Strings.HealthEditorTargetProcess;
                TargetHint.Text          = Strings.HealthEditorTargetProcessHint;
                TargetBox.Visibility     = Visibility.Visible;
                VrDeviceCombo.Visibility = Visibility.Collapsed;
                PingAdvanced.Visibility  = Visibility.Collapsed;
                break;
        }
    }

    private void OnKindChanged(object sender, RoutedEventArgs e)
    {
        if (TargetLabel is null) return; // pendant l'init avant que tout soit chargé
        var kind = KindPing.IsChecked == true ? "ping"
                 : KindVrDevice.IsChecked == true ? "vrdevice"
                 : "process";
        UpdateKindUi(kind);
    }

    private void OnIconClicked(object sender, RoutedEventArgs e)
    {
        if (sender is not Button btn || btn.Tag is not string emoji) return;
        foreach (var ic in _icons) ic.IsSelected = ic.Emoji == emoji;
    }

    private void OnSave(object sender, RoutedEventArgs e)
    {
        var name = NameBox.Text?.Trim() ?? "";
        if (string.IsNullOrEmpty(name))
        {
            ShowError(Strings.HealthEditorErrorName);
            return;
        }

        if (!int.TryParse(RefreshMsBox.Text?.Trim(), out var refreshMs) || refreshMs < 200)
        {
            ShowError(Strings.HealthEditorErrorRefresh);
            return;
        }

        var selectedIcon = _icons.FirstOrDefault(i => i.IsSelected)?.Emoji ?? Entry.Icon;

        Entry.Name = name;
        Entry.Icon = string.IsNullOrEmpty(selectedIcon) ? "🔌" : selectedIcon;
        Entry.Kind = KindPing.IsChecked == true     ? "Ping"
                   : KindVrDevice.IsChecked == true ? "VrDevice"
                                                    : "Process";

        // Target dépend du Kind : pour VrDevice, on prend la valeur de la combo
        // (alias ASCII stable comme "hmd" / "left_controller" — ne pas localiser).
        Entry.Target = Entry.Kind == "VrDevice"
            ? (VrDeviceCombo.SelectedValue as string ?? "hmd")
            : (TargetBox.Text?.Trim() ?? "");

        Entry.RefreshIntervalMs = refreshMs;

        if (Entry.Kind == "Ping")
        {
            Entry.PingWarnMs = TryParseNullableInt(PingWarnBox.Text);
            Entry.PingErrorMs = TryParseNullableInt(PingErrorBox.Text);
            Entry.PingTimeoutMs = TryParseNullableInt(PingTimeoutBox.Text);
        }

        Saved = true;
        DialogResult = true;
        Close();
    }

    private void OnCancel(object sender, RoutedEventArgs e)
    {
        DialogResult = false;
        Close();
    }

    private void ShowError(string msg)
    {
        ErrorText.Text = msg;
        ErrorText.Visibility = Visibility.Visible;
    }

    private static int? TryParseNullableInt(string? s)
    {
        if (string.IsNullOrWhiteSpace(s)) return null;
        return int.TryParse(s.Trim(), out var v) ? v : null;
    }

    /// <summary>Élément du picker d'icônes — emoji + état sélectionné pour le data trigger.</summary>
    public sealed partial class IconOption : ObservableObject
    {
        public string Emoji { get; }

        [ObservableProperty]
        private bool _isSelected;

        public IconOption(string emoji) { Emoji = emoji; }
    }

    /// <summary>Item du ComboBox VrDevice — couple alias technique + libellé affiché.</summary>
    public sealed record VrAliasOption(string Alias, string Label);
}
