using System;
using System.Collections.ObjectModel;
using System.Linq;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using PolyTrader.App.Avalonia.Controls;
using PolyTrader.Core.Modularity;
using PolyTrader.Modules.ResolutionFarming.Models;
using PolyTrader.Modules.ResolutionFarming.Persistence;
using PolyTraderSharp;

namespace PolyTrader.App.Avalonia.Views.Modules
{
    /// <summary>
    /// ResolutionFarming: Kandidaten, offene Positionen, Historie und Einstellungen je Konto.
    /// Layout vollständig in ResolutionFarmingWindow.axaml.
    /// </summary>
    public partial class ResolutionFarmingWindow : UserControl
    {
        private readonly ObservableCollection<RfCandidate> _candidates = new();
        private readonly ObservableCollection<RfPosition> _positions = new();
        private readonly ObservableCollection<RfClosedTrade> _history = new();

        private readonly TradingState _state;
        private readonly IRfCandidateRepository _candidateRepo;
        private readonly IRfPositionRepository _positionRepo;
        private readonly IRfClosedTradeRepository _closedRepo;
        private readonly IRfSettingsRepository _settingsRepo;

        private RfSettings? _currentSettings;

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

        public ResolutionFarmingWindow(IModuleUiHost host, TradingState state,
            IRfCandidateRepository candidateRepo, IRfPositionRepository positionRepo,
            IRfClosedTradeRepository closedRepo, IRfSettingsRepository settingsRepo) : this()
        {
            _state = state;
            _candidateRepo = candidateRepo;
            _positionRepo = positionRepo;
            _closedRepo = closedRepo;
            _settingsRepo = settingsRepo;

            this.FindControl<DataGrid>("gridCandidates")!.ItemsSource = _candidates;
            this.FindControl<DataGrid>("gridPositions")!.ItemsSource = _positions;
            this.FindControl<DataGrid>("gridHistory")!.ItemsSource = _history;

            this.FindControl<ComboBox>("cbAccount")!.SelectionChanged += (_, _) => LoadAll();
            this.FindControl<Button>("btnRefresh")!.Click += (_, _) => LoadAll();
            this.FindControl<Button>("btnSettingsSave")!.Click += (_, _) => SaveSettings();

            LoadAccounts();
        }

        private void LoadAccounts()
        {
            var cb = this.FindControl<ComboBox>("cbAccount")!;
            var items = _state.Accounts.Values.OrderBy(a => a.AccountId)
                .Select(a => new AccountChoice(a.AccountId, $"#{a.AccountId} {a.Name}{(a.IsDemo ? " (Demo)" : "")}"))
                .ToList();
            cb.ItemsSource = items;
            if (items.Count > 0) cb.SelectedIndex = 0; else Status("Keine Konten vorhanden.");
        }

        private int? SelectedAccountId =>
            (this.FindControl<ComboBox>("cbAccount")!.SelectedItem as AccountChoice)?.Id;

        private void Status(string text) => this.FindControl<TextBlock>("lblStatus")!.Text = text;

        private void LoadAll()
        {
            if (SelectedAccountId is not int accountId) return;
            try
            {
                _candidates.Clear();
                foreach (var c in _candidateRepo.GetRecent(accountId, 500)) _candidates.Add(c);

                _positions.Clear();
                foreach (var p in _positionRepo.GetOpen(accountId).OrderByDescending(p => p.OpenedAt)) _positions.Add(p);

                _history.Clear();
                foreach (var t in _closedRepo.Find(t => t.AccountId == accountId).OrderByDescending(t => t.Id))
                    _history.Add(t);

                this.FindControl<TextBlock>("lblPositionsSummary")!.Text =
                    $"{_positions.Count} offene Position(en) · Einsatz {_positions.Sum(p => p.AmountUsd):N2} USDC";

                decimal pnl = _history.Sum(t => t.RealizedPnl);
                int wins = _history.Count(t => t.RealizedPnl > 0m);
                decimal winrate = _history.Count > 0 ? 100m * wins / _history.Count : 0m;
                this.FindControl<TextBlock>("lblHistorySummary")!.Text =
                    $"{_history.Count} abgeschlossen · PnL {pnl:N2} USDC · Winrate {winrate:N1} %";

                _currentSettings = _settingsRepo.Get(accountId) ?? new RfSettings { AccountId = accountId };
                this.FindControl<SettingsEditor>("editorSettings")!.Show(_currentSettings);

                Status($"Geladen um {DateTime.Now:HH:mm:ss}.");
            }
            catch (Exception ex)
            {
                Status($"Laden fehlgeschlagen: {ex.Message}");
            }
        }

        private void SaveSettings()
        {
            if (_currentSettings == null) return;
            try
            {
                _settingsRepo.Upsert(_currentSettings);
                this.FindControl<TextBlock>("lblSettingsHint")!.Text =
                    $"Gespeichert für Konto #{_currentSettings.AccountId} um {DateTime.Now:HH:mm:ss}.";
            }
            catch (Exception ex)
            {
                this.FindControl<TextBlock>("lblSettingsHint")!.Text = $"Speichern fehlgeschlagen: {ex.Message}";
            }
        }

        private sealed record AccountChoice(int Id, string Label)
        {
            public override string ToString() => Label;
        }
    }
}
