using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using Microsoft.Extensions.DependencyInjection;
using PolyTrader.Core.Analytics;
using PolyTrader.Core.Modularity;
using PolyTrader.Core.Persistence;
using PolyTraderSharp.Models;

namespace PolyTraderSharp.Ui
{
    /// <summary>
    /// „Startleiste" der PolyTrader.App. Fenster werden über die im Designer platzierten
    /// Buttons in <c>toolstrip_windows</c> geöffnet bzw. in den Vordergrund geholt.
    /// <c>toolstrip_quickbar</c> ist für Schnellaktionen (z.B. Trading an/aus) reserviert,
    /// <c>statusStrip_info</c> zeigt Kernkennzahlen. Der Launcher kennt selbst kein Modul —
    /// Buttons werden per stabiler View-ID an registrierte Views gebunden.
    /// </summary>
    public partial class LauncherForm : Form
    {
        private readonly ShellUiHost _uiHost;
        private readonly IServiceProvider _services;
        private readonly TradingState _state;
        private readonly System.Windows.Forms.Timer _statusTimer = new() { Interval = 1000 };
        private readonly Dictionary<string, ToolStripButton> _viewButtons;
        private int _statusTicks;

        public LauncherForm(ShellUiHost uiHost, IServiceProvider services)
        {
            _uiHost = uiHost;
            _services = services;
            _state = services.GetRequiredService<TradingState>();

            InitializeComponent();

            _uiHost.SetMainWindow(this);

            // Fenster-Buttons: ALLE statisch im Designer, an stabile View-IDs gebunden. Ist eine View
            // nicht registriert (Modul fehlt), wird der Button deaktiviert – nichts wird zur Laufzeit angehängt.
            _viewButtons = new Dictionary<string, ToolStripButton>
            {
                ["core.dashboard"] = btn_dashboard,
                ["core.settings"] = btn_settings,
                ["core.terminal"] = btn_terminal,
                ["core.jobs"] = btn_jobs,
                ["copytrading.main"] = btn_copytrading,
                ["resolutionfarming.main"] = btn_resolutionfarming,
                ["supervisor.main"] = btn_supervisor,
                ["accounting.main"] = btn_accounting,
            };
            var registered = _uiHost.Views.Select(v => v.Id).ToHashSet();
            foreach (var (id, btn) in _viewButtons)
            {
                var viewId = id;
                if (registered.Contains(viewId))
                    btn.Click += (_, _) => _uiHost.OpenView(viewId);
                else
                    btn.Enabled = false;   // Modul/View nicht verfügbar
            }

            // Gemeinsame Fenster-Menüleiste: alle Fenster nebeneinander mit Icon (Launcher ist das
            // aktuelle Fenster → currentViewId null).
            WindowMenu.Wire(menuStrip, _uiHost, null);

            btn_liveTrading.Click += (_, _) => CycleLiveTrading();
            btn_demoTrading.Click += (_, _) => CycleDemoTrading();

            // Offen-Status der Fenster spiegeln (Button „checked", wenn Fenster offen).
            _uiHost.OpenStateChanged += UpdateWindowButtonStates;

            // Account-Übersicht (dgv_accountlist): Zahlenformate + Polymarket-Button.
            colAccBalance.DefaultCellStyle.Format = "N2";
            colAccPnl3d.DefaultCellStyle.Format = "N2";
            colAccWin3d.DefaultCellStyle.Format = "N1";
            colAccOverall.DefaultCellStyle.Format = "N2";
            dgv_accountlist.CellContentClick += AccountList_CellContentClick;

            // Live-Überblick-Widgets (Modul-PnL/Winrate, Warnungen/Fehler, auffällige Trades, Supervisor-KI).
            launcherWidgets.Initialize(_services);

            _statusTimer.Tick += (_, _) => UpdateStatus();
            _statusTimer.Start();
            UpdateStatus();
            UpdateTradingToggles();
            UpdateWindowButtonStates();
        }

        /// <summary>
        /// Fängt das Schließen des Launchers ab: Statt direkt zu beenden, läuft auch das Schließen-X
        /// über die Sicherheitsabfrage (siehe <see cref="ShellUiHost.RequestShutdown"/>). Erst wenn dort
        /// bestätigt wurde (<see cref="ShellUiHost.ShutdownConfirmed"/>), darf das Fenster schließen.
        /// </summary>
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            if (!_uiHost.ShutdownConfirmed)
            {
                e.Cancel = true;
                BeginInvoke((Action)(() => _uiHost.RequestShutdown()));
                return;
            }
            base.OnFormClosing(e);
        }

        private void UpdateWindowButtonStates()
        {
            if (IsDisposed) return;
            foreach (var (id, btn) in _viewButtons)
                btn.Checked = _uiHost.IsOpen(id);
        }

        private void CycleLiveTrading()
        {
            _state.LiveTradingMode = _state.LiveTradingMode switch
            {
                TradingMode.Inactive => TradingMode.SellOnly,
                TradingMode.SellOnly => TradingMode.Active,
                _ => TradingMode.Inactive
            };
            UpdateTradingToggles();
        }

        private void CycleDemoTrading()
        {
            _state.DemoTradingMode = _state.DemoTradingMode switch
            {
                TradingMode.Inactive => TradingMode.SellOnly,
                TradingMode.SellOnly => TradingMode.Active,
                _ => TradingMode.Inactive
            };
            UpdateTradingToggles();
        }

        private void UpdateTradingToggles()
        {
            ApplyToggle(btn_liveTrading, "LiveTrading", _state.LiveTradingMode);
            ApplyToggle(btn_demoTrading, "DemoTrading", _state.DemoTradingMode);

            static void ApplyToggle(ToolStripButton btn, string label, TradingMode mode)
            {
                switch (mode)
                {
                    case TradingMode.Active:
                        btn.Text = $"{label} (AKTIV)";
                        btn.BackColor = System.Drawing.Color.LightGreen;
                        break;
                    case TradingMode.SellOnly:
                        btn.Text = $"{label} (SELL-ONLY)";
                        btn.BackColor = System.Drawing.Color.Orange;
                        break;
                    default:
                        btn.Text = $"{label} (DEAKTIVIERT)";
                        btn.BackColor = System.Drawing.Color.IndianRed;
                        break;
                }
            }
        }

        private void UpdateStatus()
        {
            string trading = _state.GlobalTradingPaused
                ? "Pausiert"
                : $"Live={_state.LiveTradingMode} / Demo={_state.DemoTradingMode}";
            lbl_trading.Text = $"Trading: {trading}";

            int moduleCount = _services.GetServices<IPolyTraderModule>().Count();
            lbl_modules.Text = $"Module: {moduleCount}";

            lbl_ratelimit.Text = $"API: {(_state.IsAlchemyHealthy ? "WSS aktiv" : "Polling")}";

            UpdateTradingToggles();
            UpdateWindowButtonStates();

            // Account-Übersicht + Widgets alle 30 s aktualisieren (DB-Abfragen – nicht jede Sekunde).
            if (_statusTicks++ % 30 == 0)
            {
                LoadAccountOverview();
                launcherWidgets.RefreshData();
            }
        }

        // ===== Account-Übersicht (dgv_accountlist) =====

        private void LoadAccountOverview()
        {
            if (IsDisposed) return;
            var tradeLog = _services.GetService<ITradeLogRepository>();
            if (tradeLog == null) return;

            DateTime since3d = DateTime.UtcNow.AddDays(-3);
            var rows = new List<AccountOverviewRow>();

            foreach (var acc in _state.Accounts.Values.OrderBy(a => a.AccountId))
            {
                List<TradeRecord> trades;
                try { trades = tradeLog.Find(t => t.AccountId == acc.AccountId); }
                catch { trades = new List<TradeRecord>(); }   // DB nicht bereit -> leer statt Absturz

                var (pnl3d, win3d, _) = TradeAnalytics.WindowSummary(trades.Where(t => t.ClosedAt >= since3d));
                string modules = trades
                    .Select(t => t.ModuleName)
                    .Where(m => !string.IsNullOrEmpty(m))
                    .Distinct().OrderBy(m => m)
                    .DefaultIfEmpty("—")
                    .Aggregate((a, b) => a + ", " + b);

                rows.Add(new AccountOverviewRow
                {
                    AccountId = acc.AccountId,
                    Name = (string.IsNullOrEmpty(acc.Name) ? $"#{acc.AccountId}" : acc.Name) + (acc.IsDemo ? " (Demo)" : ""),
                    Modules = modules,
                    WalletAddress = acc.WalletAddress,
                    Balance = acc.TotalBalance,
                    Pnl3d = pnl3d,
                    WinRate3d = win3d,
                    OverallPnl = trades.Sum(t => t.RealizedPnl)
                });
            }

            dgv_accountlist.DataSource = rows;
        }

        private void AccountList_CellContentClick(object? sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex < 0 || e.ColumnIndex < 0) return;
            if (dgv_accountlist.Columns[e.ColumnIndex].Name != "colAccPoly") return;
            if (dgv_accountlist.Rows[e.RowIndex].DataBoundItem is AccountOverviewRow row)
                OpenPolymarketProfile(row.WalletAddress);
        }

        private void OpenPolymarketProfile(string walletAddress)
        {
            if (string.IsNullOrWhiteSpace(walletAddress))
            {
                MessageBox.Show("Für diesen Account ist keine Wallet-Adresse hinterlegt.", "Polymarket",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            try
            {
                Process.Start(new ProcessStartInfo
                {
                    FileName = $"https://polymarket.com/profile/{walletAddress}",
                    UseShellExecute = true
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Konnte Polymarket nicht öffnen: {ex.Message}", "Fehler",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>Anzeige-Zeile der Account-Übersicht (Bindung an dgv_accountlist über DataPropertyName).</summary>
        private sealed class AccountOverviewRow
        {
            public int AccountId { get; set; }
            public string Name { get; set; } = string.Empty;
            public string Modules { get; set; } = string.Empty;
            public string WalletAddress { get; set; } = string.Empty;
            public decimal Balance { get; set; }
            public decimal Pnl3d { get; set; }
            public decimal WinRate3d { get; set; }
            public decimal OverallPnl { get; set; }
        }
    }
}
