using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using PolyTrader.Core.Modularity;

namespace PolyTraderSharp.Ui
{
    /// <summary>
    /// Verwaltet die registrierten Fenster-Views: öffnet sie als eigenständige Forms,
    /// hält je View höchstens eine Instanz offen und holt ein bereits offenes Fenster
    /// wieder in den Vordergrund. Meldet Änderungen am Offen-Status (für die
    /// Button-Markierung im Launcher).
    /// </summary>
    public class ShellUiHost : IModuleUiHost
    {
        private readonly List<ModuleView> _views = new();
        private readonly Dictionary<string, Form> _open = new();
        private Form? _mainWindow;
        private bool _shutdownDialogOpen;

        /// <summary>
        /// True, sobald das Herunterfahren über die Sicherheitsabfrage bestätigt wurde. Der Launcher
        /// wertet das in FormClosing aus, um beim Schließen-X denselben Dialog zu erzwingen.
        /// </summary>
        public bool ShutdownConfirmed { get; private set; }

        /// <summary>Wird ausgelöst, wenn sich der Offen-Status irgendeiner View ändert.</summary>
        public event Action? OpenStateChanged;

        public IReadOnlyList<ModuleView> Views => _views;

        public void RegisterView(ModuleView view) => _views.Add(view);

        /// <summary>Setzt das Hauptfenster (Launcher) – Ziel für <see cref="ActivateMain"/>.</summary>
        public void SetMainWindow(Form main) => _mainWindow = main;

        /// <summary>
        /// Fügt einem Fenster die gemeinsame Fenster-Menüleiste hinzu (oberste Leiste, alle Fenster
        /// nebeneinander mit Icon). Als letztes hinzugefügtes Top-Control belegt der MenuStrip die
        /// oberste Zeile über etwaigen ToolStrips.
        /// </summary>
        private void AttachWindowMenu(Form form, string currentViewId)
        {
            var menu = new MenuStrip { Dock = DockStyle.Top, ImageScalingSize = new System.Drawing.Size(24, 24) };
            WindowMenu.Wire(menu, this, currentViewId);
            form.Controls.Add(menu);
            form.MainMenuStrip = menu;
        }

        public void ActivateMain()
        {
            if (_mainWindow == null || _mainWindow.IsDisposed) return;
            if (_mainWindow.WindowState == FormWindowState.Minimized)
                _mainWindow.WindowState = FormWindowState.Maximized;
            _mainWindow.BringToFront();
            _mainWindow.Activate();
        }

        public bool IsOpen(string viewId) =>
            _open.TryGetValue(viewId, out var form) && !form.IsDisposed;

        /// <summary>
        /// Zeigt die Sicherheitsabfrage (Timer-gesperrter Beenden-Button, Abbrechen jederzeit). Bei
        /// Bestätigung wird die Message-Loop beendet – das geordnete Herunterfahren der Module läuft
        /// anschließend in Program.Main über <c>AppHost.StopAsync()</c> (nach <c>Application.Run</c>).
        /// Aus jedem Fenster aufrufbar; der Dialog erscheint zentriert über dem Hauptfenster.
        /// </summary>
        public void RequestShutdown()
        {
            if (ShutdownConfirmed || _shutdownDialogOpen) return;
            _shutdownDialogOpen = true;
            try
            {
                using var dlg = new ShutdownConfirmDialog();
                var owner = _mainWindow != null && !_mainWindow.IsDisposed ? _mainWindow : null;
                var result = owner != null ? dlg.ShowDialog(owner) : dlg.ShowDialog();
                if (result != DialogResult.OK) return;

                ShutdownConfirmed = true;
                Application.Exit();   // beendet die Message-Loop; StopAsync() fährt Module danach sauber herunter
            }
            finally
            {
                _shutdownDialogOpen = false;
            }
        }

        public void OpenView(string viewId)
        {
            var view = _views.FirstOrDefault(v => v.Id == viewId);
            if (view != null) OpenView(view);
        }

        public void OpenView(ModuleView view)
        {
            if (_open.TryGetValue(view.Id, out var existing) && !existing.IsDisposed)
            {
                if (existing.WindowState == FormWindowState.Minimized)
                    existing.WindowState = FormWindowState.Normal;
                existing.BringToFront();
                existing.Activate();
                return;
            }

            // CreateView liefert bewusst object (toolkit-neutraler Core-Contract). Die WinForms-Shell
            // kennt ihr Toolkit und castet hier; ein falscher Typ ist ein Programmierfehler und soll
            // laut knallen, nicht still ein leeres Fenster erzeugen.
            var form = (Form)view.CreateView();
            if (string.IsNullOrEmpty(form.Text) || form.Text == form.Name)
                form.Text = view.Title;

            // Gemeinsames „Fenster"-Menü zentral in jedes Fenster injizieren (identische Shell-Chrome
            // auf allen Fenstern; die inhaltlichen Controls bleiben designerbasiert). Nur, wenn das
            // Fenster nicht bereits ein eigenes Menü mitbringt (z. B. der Launcher).
            if (form.MainMenuStrip == null)
                AttachWindowMenu(form, view.Id);

            // Alle Fenster maximiert (Vorgabe): Full-HD-Ziel, skaliert auf größere Auflösungen.
            form.StartPosition = FormStartPosition.CenterScreen;
            form.WindowState = FormWindowState.Maximized;

            _open[view.Id] = form;
            form.FormClosed += (_, _) =>
            {
                _open.Remove(view.Id);
                OpenStateChanged?.Invoke();
            };

            form.Show();
            OpenStateChanged?.Invoke();
        }
    }
}
