using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using PolyTrader.Core.Analytics;
using PolyTrader.Core.Persistence;
using PolyTraderSharp.Services;

namespace PolyTrader.Modules.Supervisor.Services
{
    /// <summary>Kopfzeile eines Signals für die Übersichtsliste des Dossier-Browsers.</summary>
    public sealed record SignalSummary(
        string SignalId, DateTime FirstSeen, string ModuleName, int AccountId,
        string Side, string MarketQuestion, string LastDecision, string LastReason, int DecisionCount);

    /// <summary>
    /// Beschafft die Daten für Trade-Dossiers (S-1): Entscheidungsjournal + Order-Events +
    /// Core-Trade-Log + JSONL-Log-Zeilen (per CorrelationId), Zusammenbau/Rendering pur im
    /// <see cref="DossierBuilder"/> (Core). Read-only — der Supervisor ist Beobachter.
    /// </summary>
    public class DossierService
    {
        private readonly IDecisionJournal _journal;
        private readonly IOrderEventLog _orderEvents;
        private readonly ITradeLogRepository _tradeLog;
        private readonly string _logsDirectory;

        public DossierService(IDecisionJournal journal, IOrderEventLog orderEvents, ITradeLogRepository tradeLog)
        {
            _journal = journal;
            _orderEvents = orderEvents;
            _tradeLog = tradeLog;
            _logsDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
        }

        /// <summary>Jüngste Signale (gruppiert über das Entscheidungsjournal), neueste zuerst.</summary>
        public List<SignalSummary> RecentSignals(int limit = 200)
        {
            var decisions = _journal.Query(d => d.SignalId != "", limit * 5);
            return decisions
                .GroupBy(d => d.SignalId)
                .Select(g =>
                {
                    var ordered = g.OrderBy(d => d.Timestamp).ToList();
                    var first = ordered[0];
                    var last = ordered[^1];
                    return new SignalSummary(g.Key, first.Timestamp, first.ModuleName, first.AccountId,
                        first.Side, first.MarketQuestion, last.Decision.ToString(), last.Reason.ToString(), ordered.Count);
                })
                .OrderByDescending(s => s.FirstSeen)
                .Take(limit)
                .ToList();
        }

        /// <summary>Baut das komplette Dossier zu einer SignalId (inkl. Log-Zeilen aus den JSONL-Tagesdateien).</summary>
        public TradeDossier BuildForSignal(string signalId)
        {
            var decisions = _journal.Query(d => d.SignalId == signalId);
            var events = _orderEvents.Query(e => e.SignalId == signalId);
            var trades = _tradeLog.Find(t => t.SignalId == signalId);
            var logLines = ReadLogLines(signalId, decisions.Select(d => d.Timestamp).Concat(events.Select(e => e.Timestamp)));
            return DossierBuilder.Build(signalId, decisions, events, trades, logLines);
        }

        /// <summary>
        /// Liest JSONL-Zeilen mit passender CorrelationId — nur aus den Tagesdateien im Zeitfenster der
        /// bekannten Ereignisse (±1 Tag), statt alle Logs zu scannen. Fehlertolerant (fehlende Dateien = leer).
        /// </summary>
        private List<LogJson.ParsedLogLine> ReadLogLines(string signalId, IEnumerable<DateTime> eventTimes)
        {
            var result = new List<LogJson.ParsedLogLine>();
            var times = eventTimes.ToList();
            if (times.Count == 0 || string.IsNullOrEmpty(signalId)) return result;

            try
            {
                var from = times.Min().Date.AddDays(-1);
                var to = times.Max().Date.AddDays(1);
                for (var day = from; day <= to; day = day.AddDays(1))
                {
                    string path = Path.Combine(_logsDirectory, $"{day:yyyy-MM-dd}.jsonl");
                    if (!File.Exists(path)) continue;
                    foreach (var line in File.ReadLines(path))
                    {
                        var p = LogJson.ParseLine(line);
                        if (p != null && p.Cid == signalId) result.Add(p);
                    }
                }
            }
            catch { /* Log-Auszug ist Beiwerk – Dossier bleibt auch ohne nutzbar */ }
            return result;
        }
    }
}
