using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Microsoft.Extensions.DependencyInjection;
using PolyTrader.Core.Analytics;
using PolyTrader.Core.Persistence;
using PolyTrader.Modules.Supervisor.Persistence;
using PolyTraderSharp.Models;
using PolyTraderSharp.Services;

namespace PolyTraderSharp.Ui
{
    /// <summary>
    /// Live-Überblick-Widgets für den Launcher (Slice 4): Modul-PnL/Winrate-Kacheln, Supervisor-KI-
    /// Kurzfassung, Warnungen/Fehler aus den Logs und auffällige Trades. Isoliert als UserControl,
    /// damit der Launcher-Designer schlank bleibt. Alle Datenzugriffe defensiv (Widgets dürfen den
    /// Launcher nie brechen). Layout im Designer (LauncherWidgetsPanel.Designer.cs).
    /// </summary>
    public partial class LauncherWidgetsPanel : UserControl
    {
        private ITradeLogRepository? _tradeLog;
        private ISupervisorReportRepository? _reports;
        private readonly string _logsDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");

        public LauncherWidgetsPanel()
        {
            InitializeComponent();
            colNotPnl.DefaultCellStyle.Format = "F2";
            colNotPnlPct.DefaultCellStyle.Format = "F1";
        }

        public void Initialize(IServiceProvider services)
        {
            _tradeLog = services.GetService<ITradeLogRepository>();
            _reports = services.GetService<ISupervisorReportRepository>();
            RefreshData();
        }

        /// <summary>Aktualisiert alle Widgets. Wird vom Launcher periodisch aufgerufen.</summary>
        public void RefreshData()
        {
            if (IsDisposed) return;
            UpdateModuleKpis();
            UpdateAlerts();
            UpdateNotable();
            UpdateSupervisor();
        }

        // ----- Modul-PnL/Winrate-Kacheln -----

        private void UpdateModuleKpis()
        {
            flpKpis.SuspendLayout();
            flpKpis.Controls.Clear();
            try
            {
                var since = DateTime.UtcNow.AddDays(-30);
                List<TradeRecord> all = _tradeLog?.Find(t => t.ClosedAt >= since) ?? new List<TradeRecord>();

                DateTime today = DateTime.UtcNow.Date;
                DateTime week = DateTime.UtcNow.AddDays(-7);

                foreach (var module in all.Select(t => t.ModuleName).Where(m => !string.IsNullOrEmpty(m)).Distinct().OrderBy(m => m))
                    flpKpis.Controls.Add(BuildTile(module, all.Where(t => t.ModuleName == module).ToList(), today, week));

                flpKpis.Controls.Add(BuildTile("Gesamt", all, today, week));

                if (flpKpis.Controls.Count == 1)   // nur "Gesamt", keine Trades
                    flpKpis.Controls.Add(new Label { AutoSize = true, Margin = new Padding(6), ForeColor = Color.Gray, Text = "Noch keine abgeschlossenen Trades." });
            }
            catch (Exception ex)
            {
                flpKpis.Controls.Add(new Label { AutoSize = true, ForeColor = Color.Firebrick, Text = $"KPIs n/v: {ex.Message}" });
            }
            flpKpis.ResumeLayout();
        }

        private static Label BuildTile(string module, List<TradeRecord> moduleTrades, DateTime today, DateTime week)
        {
            decimal todayPnl = moduleTrades.Where(t => t.ClosedAt >= today).Sum(t => t.RealizedPnl);
            var k7 = TradeAnalytics.ComputeKpis(moduleTrades.Where(t => t.ClosedAt >= week));
            var k30 = TradeAnalytics.ComputeKpis(moduleTrades);

            var tile = new Label
            {
                AutoSize = false,
                Width = 252,
                Height = 92,
                BorderStyle = BorderStyle.FixedSingle,
                Margin = new Padding(3),
                Padding = new Padding(7),
                TextAlign = ContentAlignment.TopLeft,
                Font = new Font("Segoe UI", 9F),
                Text = $"{module}\n" +
                       $"Heute: {todayPnl:+0.00;-0.00} USDC\n" +
                       $"7T:  {k7.NetPnl:+0.00;-0.00} · {k7.WinRatePct:0}% · {k7.TradeCount} Tr.\n" +
                       $"30T: {k30.NetPnl:+0.00;-0.00} · {k30.WinRatePct:0}%"
            };
            tile.ForeColor = k30.NetPnl >= 0 ? Color.ForestGreen : Color.Firebrick;
            return tile;
        }

        // ----- Warnungen & Fehler (heute, JSONL) -----

        private void UpdateAlerts()
        {
            try
            {
                string path = Path.Combine(_logsDir, $"{DateTime.Now:yyyy-MM-dd}.jsonl");
                var rows = new List<AlertRow>();
                if (File.Exists(path))
                {
                    foreach (var line in File.ReadLines(path))
                    {
                        var p = LogJson.ParseLine(line);
                        if (p == null) continue;
                        if (p.Level != "Error" && p.Level != "Warning") continue;
                        rows.Add(new AlertRow { Time = ShortTime(p.Time), Level = p.Level, Message = OneLine(p.Message) });
                    }
                }
                rows.Reverse();   // neueste zuerst
                dgvAlerts.DataSource = rows.Take(200).ToList();
                grpAlerts.Text = $"Warnungen & Fehler (heute): {rows.Count}";
            }
            catch (Exception ex)
            {
                grpAlerts.Text = $"Warnungen & Fehler – n/v ({ex.Message})";
            }
        }

        // ----- Auffällige Trades (24h) -----

        private void UpdateNotable()
        {
            try
            {
                var since = DateTime.UtcNow.AddDays(-1);
                var rows = (_tradeLog?.Find(t => t.ClosedAt >= since) ?? new List<TradeRecord>())
                    .OrderByDescending(t => Math.Abs(t.RealizedPnl))
                    .Take(30)
                    .Select(t => new NotableRow
                    {
                        Module = t.ModuleName,
                        Market = t.MarketQuestion,
                        Pnl = t.RealizedPnl,
                        PnlPct = t.PnlPercent
                    })
                    .ToList();
                dgvNotable.DataSource = rows;
            }
            catch (Exception ex)
            {
                grpNotable.Text = $"Auffällige Trades – n/v ({ex.Message})";
            }
        }

        // ----- Supervisor-KI-Kurzfassung -----

        private void UpdateSupervisor()
        {
            if (_reports == null)
            {
                rtbSupervisor.Text = "Supervisor-Modul nicht verfügbar.";
                return;
            }
            try
            {
                var last = _reports.GetRecent(1).FirstOrDefault();
                rtbSupervisor.Text = last == null
                    ? "Noch kein Supervisor-Bericht. (OpenRouter-Key setzen und im Supervisor-Fenster eine Analyse starten.)"
                    : $"[{last.CreatedAt:dd.MM. HH:mm}] {last.Profile} · {last.Model}\n\n{last.Answer}";
            }
            catch (Exception ex)
            {
                rtbSupervisor.Text = $"Supervisor-Berichte n/v: {ex.Message}";
            }
        }

        // ----- Helfer -----

        private static string ShortTime(string iso) =>
            DateTime.TryParse(iso, out var dt) ? dt.ToString("HH:mm:ss") : iso;

        private static string OneLine(string s) =>
            (s ?? string.Empty).Replace("\r", " ").Replace("\n", " ").Trim();

        private sealed class AlertRow
        {
            public string Time { get; set; } = string.Empty;
            public string Level { get; set; } = string.Empty;
            public string Message { get; set; } = string.Empty;
        }

        private sealed class NotableRow
        {
            public string Module { get; set; } = string.Empty;
            public string Market { get; set; } = string.Empty;
            public decimal Pnl { get; set; }
            public decimal PnlPct { get; set; }
        }
    }
}
