using System;
using System.Collections.ObjectModel;
using System.Linq;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using PolyTrader.App.Avalonia.ViewModels;
using PolyTrader.Core.Analytics;
using PolyTrader.Core.Modularity;
using PolyTrader.Modules.Supervisor.Agent;
using PolyTrader.Modules.Supervisor.Counterfactual;
using PolyTrader.Modules.Supervisor.Persistence;
using PolyTrader.Modules.Supervisor.Services;
using PolyTraderSharp.Services;

namespace PolyTrader.App.Avalonia.Views.Modules
{
    /// <summary>
    /// Supervisor: Analyse-Chat gegen den Agenten, Dossiers je Signal, gespeicherte Berichte und
    /// Counterfactuals. Layout vollständig in SupervisorWindow.axaml.
    /// </summary>
    public partial class SupervisorWindow : UserControl
    {
        private readonly ObservableCollection<ChatEntry> _chat = new();
        private readonly ObservableCollection<SignalSummary> _signals = new();
        private readonly ObservableCollection<SupervisorReport> _reports = new();
        private readonly ObservableCollection<CounterfactualRecord> _counterfactuals = new();

        private readonly SupervisorAgent _agent = null!;
        private readonly DossierService _dossiers = null!;
        private readonly ISupervisorReportRepository _reportRepo = null!;
        private readonly ISupervisorCounterfactualRepository _cfRepo = null!;
        private readonly TerminalLogger _logger = null!;

        public SupervisorWindow() => AvaloniaXamlLoader.Load(this);

        public SupervisorWindow(IModuleUiHost host, SupervisorAgent agent, DossierService dossiers,
            ISupervisorReportRepository reportRepo, ISupervisorCounterfactualRepository cfRepo,
            TerminalLogger logger) : this()
        {
            _agent = agent;
            _dossiers = dossiers;
            _reportRepo = reportRepo;
            _cfRepo = cfRepo;
            _logger = logger;

            this.FindControl<ItemsControl>("chatLines")!.ItemsSource = _chat;
            this.FindControl<DataGrid>("gridSignals")!.ItemsSource = _signals;
            this.FindControl<DataGrid>("gridReports")!.ItemsSource = _reports;
            this.FindControl<DataGrid>("gridCounterfactual")!.ItemsSource = _counterfactuals;

            var cbProfile = this.FindControl<ComboBox>("cbProfile")!;
            cbProfile.ItemsSource = SupervisorProfiles.All.ToList();
            cbProfile.SelectedIndex = 0;

            this.FindControl<Button>("btnSend")!.Click += async (_, _) => await AskAsync();
            this.FindControl<Button>("btnClearChat")!.Click += (_, _) => _chat.Clear();
            this.FindControl<Button>("btnDossierRefresh")!.Click += (_, _) => LoadSignals();
            this.FindControl<Button>("btnDossierOpen")!.Click += (_, _) => OpenDossier();
            this.FindControl<Button>("btnReportsRefresh")!.Click += (_, _) => LoadReports();
            this.FindControl<Button>("btnCfRefresh")!.Click += (_, _) => LoadCounterfactuals();

            // Auswahl im Signal-Grid übernimmt die SignalId ins Eingabefeld.
            this.FindControl<DataGrid>("gridSignals")!.SelectionChanged += (_, _) =>
            {
                if (this.FindControl<DataGrid>("gridSignals")!.SelectedItem is SignalSummary s)
                    this.FindControl<TextBox>("tbSignalId")!.Text = s.SignalId;
            };

            LoadSignals();
            LoadReports();
            LoadCounterfactuals();
        }

        // ===== Analyse =====

        private async System.Threading.Tasks.Task AskAsync()
        {
            var tbQuestion = this.FindControl<TextBox>("tbQuestion")!;
            string question = tbQuestion.Text?.Trim() ?? string.Empty;
            if (question.Length == 0) return;

            var btn = this.FindControl<Button>("btnSend")!;
            var status = this.FindControl<TextBlock>("lblChatStatus")!;

            AddChat("Du", question, ChatRole.User);
            tbQuestion.Text = string.Empty;
            btn.IsEnabled = false;
            status.Text = "Der Supervisor denkt nach …";

            try
            {
                var profile = this.FindControl<ComboBox>("cbProfile")!.SelectedItem as SupervisorProfile;
                string? model = this.FindControl<TextBox>("tbModel")!.Text?.Trim();
                if (string.IsNullOrWhiteSpace(model)) model = null;

                // Zwischenmeldungen des Agenten (Tool-Aufrufe) laufen über die Statuszeile.
                var progress = new Progress<string>(m => Dispatcher.UIThread.Post(() => status.Text = m));

                var result = await _agent.AskAsync(question, model, progress, profile);

                AddChat($"Supervisor ({profile?.Name ?? "Allgemein"})", result.Answer, ChatRole.Agent);
                status.Text = $"{result.ToolInvocations.Count} Tool-Aufruf(e) · " +
                              $"{result.PromptTokens + result.CompletionTokens} Token.";
            }
            catch (Exception ex)
            {
                AddChat("Fehler", ex.Message, ChatRole.Error);
                status.Text = "Anfrage fehlgeschlagen.";
                _logger.Error($"Supervisor-Anfrage fehlgeschlagen: {ex.Message}");
            }
            finally
            {
                btn.IsEnabled = true;
                LoadReports();   // die Anfrage wurde als Bericht abgelegt
            }
        }

        private void AddChat(string who, string text, ChatRole role)
        {
            _chat.Add(new ChatEntry { Header = $"[{DateTime.Now:HH:mm:ss}] {who}", Text = text, Role = role });
            this.FindControl<ScrollViewer>("chatScroll")!.ScrollToEnd();
        }

        // ===== Dossiers =====

        private void LoadSignals()
        {
            try
            {
                _signals.Clear();
                foreach (var s in _dossiers.RecentSignals(200)) _signals.Add(s);
            }
            catch (Exception ex)
            {
                _logger.Error($"Signale konnten nicht geladen werden: {ex.Message}");
            }
        }

        private void OpenDossier()
        {
            string signalId = this.FindControl<TextBox>("tbSignalId")!.Text?.Trim() ?? string.Empty;
            var target = this.FindControl<SelectableTextBlock>("txtDossier")!;
            if (signalId.Length == 0)
            {
                target.Text = "Bitte eine SignalId auswählen oder eingeben.";
                return;
            }

            try
            {
                var dossier = _dossiers.BuildForSignal(signalId);
                target.Text = DossierBuilder.ToMarkdown(dossier);
            }
            catch (Exception ex)
            {
                target.Text = $"Dossier konnte nicht erstellt werden: {ex.Message}";
            }
        }

        // ===== Berichte / Counterfactual =====

        private void LoadReports()
        {
            try
            {
                _reports.Clear();
                foreach (var r in _reportRepo.GetRecent(200)) _reports.Add(r);
            }
            catch (Exception ex)
            {
                _logger.Error($"Berichte konnten nicht geladen werden: {ex.Message}");
            }
        }

        private void LoadCounterfactuals()
        {
            try
            {
                _counterfactuals.Clear();
                foreach (var c in _cfRepo.GetRecent(500)) _counterfactuals.Add(c);
            }
            catch (Exception ex)
            {
                _logger.Error($"Counterfactuals konnten nicht geladen werden: {ex.Message}");
            }
        }
    }
}
