using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using PSLauncher.Core.Localization;

namespace PSLauncher.App.Views;

/// <summary>
/// Drop-in pour <see cref="System.Windows.MessageBox"/> avec un look qui colle
/// au reste de la UI (dark theme, accent ASTERION). API copiée :
/// <code>
///   ThemedMessageBox.Show("Texte", "Titre", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
/// </code>
///
/// Notes :
/// - <see cref="MessageBoxImage"/> est mappé vers une icône emoji + couleur.
/// - Les libellés des boutons (OK / Yes / No / Cancel) sont localisés via <see cref="Strings"/>.
/// - Owner = MainWindow par défaut (centrage), peut être passé explicitement.
/// - Esc renvoie Cancel ou No selon le bouton défini comme cancel.
/// </summary>
public partial class ThemedMessageBox : Window
{
    public MessageBoxResult Result { get; private set; } = MessageBoxResult.None;

    private MessageBoxResult _btn1Result = MessageBoxResult.None;
    private MessageBoxResult _btn2Result = MessageBoxResult.None;
    private MessageBoxResult _btn3Result = MessageBoxResult.None;

    private ThemedMessageBox(string message, string title, MessageBoxButton button,
                             MessageBoxImage icon, MessageBoxResult defaultResult)
    {
        InitializeComponent();

        Title = title;
        TitleText.Text = title;
        MessageText.Text = message;
        SetIcon(icon);
        SetupButtons(button, defaultResult);

        // Esc = cancel/no
        PreviewKeyDown += (_, e) =>
        {
            if (e.Key == Key.Escape)
            {
                Result = button switch
                {
                    MessageBoxButton.OK            => MessageBoxResult.OK,
                    MessageBoxButton.OKCancel      => MessageBoxResult.Cancel,
                    MessageBoxButton.YesNo         => MessageBoxResult.No,
                    MessageBoxButton.YesNoCancel   => MessageBoxResult.Cancel,
                    _                               => MessageBoxResult.None,
                };
                DialogResult = false;
                Close();
            }
        };
    }

    private void SetIcon(MessageBoxImage icon)
    {
        // NOTE : MessageBoxImage.Stop ≡ Error (16) et Asterisk ≡ Information (64)
        // côté enum .NET, donc on ne switche que sur les noms canoniques.
        switch (icon)
        {
            case MessageBoxImage.Error:    // = Stop = Hand
                IconText.Text = "⛔";
                IconText.Foreground = new SolidColorBrush(Color.FromRgb(0xEF, 0x44, 0x44));
                break;
            case MessageBoxImage.Warning:  // = Exclamation
                IconText.Text = "⚠";
                IconText.Foreground = new SolidColorBrush(Color.FromRgb(0xF5, 0x9E, 0x0B));
                break;
            case MessageBoxImage.Question:
                IconText.Text = "❓";
                break;
            case MessageBoxImage.Information:  // = Asterisk
                IconText.Text = "ℹ";
                IconText.Foreground = new SolidColorBrush(Color.FromRgb(0x3B, 0x82, 0xF6));
                break;
            default:
                IconText.Visibility = Visibility.Collapsed;
                break;
        }
    }

    /// <summary>
    /// Configure jusqu'à 3 boutons. L'ordre visuel est gauche → droite, avec
    /// le bouton "principal" (default) en accent à l'extrême droite. Les autres
    /// en secondary à gauche.
    /// </summary>
    private void SetupButtons(MessageBoxButton button, MessageBoxResult defaultResult)
    {
        // Liste (label, result) dans l'ordre où on veut les afficher
        var btns = button switch
        {
            MessageBoxButton.OK            => new[] { (Strings.ActionOk, MessageBoxResult.OK) },
            MessageBoxButton.OKCancel      => new[] {
                (Strings.ActionCancel, MessageBoxResult.Cancel),
                (Strings.ActionOk,     MessageBoxResult.OK),
            },
            MessageBoxButton.YesNo         => new[] {
                (Strings.ActionNo,  MessageBoxResult.No),
                (Strings.ActionYes, MessageBoxResult.Yes),
            },
            MessageBoxButton.YesNoCancel   => new[] {
                (Strings.ActionCancel, MessageBoxResult.Cancel),
                (Strings.ActionNo,     MessageBoxResult.No),
                (Strings.ActionYes,    MessageBoxResult.Yes),
            },
            _ => new[] { (Strings.ActionOk, MessageBoxResult.OK) },
        };

        // Btn3 = bouton accent (le plus à droite, principal). Toujours rempli.
        // Btn2 = secondary à sa gauche, optionnel.
        // Btn1 = secondary tout à gauche, optionnel.
        // On remplit en partant de la fin pour que l'accent soit toujours sur Btn3.
        var slots = new[] { Btn1, Btn2, Btn3 };
        var resultSetters = new System.Action<MessageBoxResult>[]
        {
            r => _btn1Result = r,
            r => _btn2Result = r,
            r => _btn3Result = r,
        };

        int startSlot = 3 - btns.Length;
        for (int i = 0; i < btns.Length; i++)
        {
            int slotIdx = startSlot + i;
            slots[slotIdx].Content = btns[i].Item1;
            slots[slotIdx].Visibility = Visibility.Visible;
            resultSetters[slotIdx](btns[i].Item2);
            // Default = celui dont le result match defaultResult
            if (btns[i].Item2 == defaultResult)
                slots[slotIdx].IsDefault = true;
        }

        // Si aucun match exact pour le default, on prend le bouton principal (Btn3)
        if (Btn3.Visibility == Visibility.Visible && !Btn1.IsDefault && !Btn2.IsDefault && !Btn3.IsDefault)
            Btn3.IsDefault = true;
    }

    private void OnBtn1Click(object sender, RoutedEventArgs e) => Finish(_btn1Result);
    private void OnBtn2Click(object sender, RoutedEventArgs e) => Finish(_btn2Result);
    private void OnBtn3Click(object sender, RoutedEventArgs e) => Finish(_btn3Result);

    private void Finish(MessageBoxResult result)
    {
        Result = result;
        DialogResult = true;
        Close();
    }

    // ===================== STATIC SHOW OVERLOADS =====================

    public static MessageBoxResult Show(string message)
        => Show(message, string.Empty, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.OK);

    public static MessageBoxResult Show(string message, string title)
        => Show(message, title, MessageBoxButton.OK, MessageBoxImage.None, MessageBoxResult.OK);

    public static MessageBoxResult Show(string message, string title, MessageBoxButton button)
        => Show(message, title, button, MessageBoxImage.None, DefaultFor(button));

    public static MessageBoxResult Show(string message, string title, MessageBoxButton button, MessageBoxImage icon)
        => Show(message, title, button, icon, DefaultFor(button));

    public static MessageBoxResult Show(string message, string title, MessageBoxButton button,
                                        MessageBoxImage icon, MessageBoxResult defaultResult)
    {
        var owner = Application.Current?.Windows.OfType<Window>().FirstOrDefault(w => w.IsActive)
                 ?? Application.Current?.MainWindow;
        var dlg = new ThemedMessageBox(message, title, button, icon, defaultResult);
        if (owner is not null && owner.IsVisible) dlg.Owner = owner;
        else dlg.WindowStartupLocation = WindowStartupLocation.CenterScreen;
        dlg.ShowDialog();
        return dlg.Result;
    }

    private static MessageBoxResult DefaultFor(MessageBoxButton button) => button switch
    {
        MessageBoxButton.OK            => MessageBoxResult.OK,
        MessageBoxButton.OKCancel      => MessageBoxResult.OK,
        MessageBoxButton.YesNo         => MessageBoxResult.Yes,
        MessageBoxButton.YesNoCancel   => MessageBoxResult.Yes,
        _                               => MessageBoxResult.None,
    };
}
