using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using LiveChartsCore;
using LiveChartsCore.Defaults;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Painting;
using PolyTrader.Core.Analytics;
using PolyTraderSharp.Models;
using SkiaSharp;

namespace PolyTrader.App.Avalonia.ViewModels
{
    /// <summary>
    /// Datenmodell der drei Dashboard-Diagramme (LiveCharts2). Ersetzt das frühere Rendern nach
    /// Bitmap: die Diagramme sind jetzt echte Steuerelemente – interaktiv und ohne System.Drawing.
    ///
    /// <para>Die Auswertung selbst kommt unverändert aus <see cref="TradeAnalytics"/>; dieses Modell
    /// übersetzt deren Ergebnisse nur in Serien und Achsen. Die Trennung war schon vorher da und ist
    /// der Grund, warum der Chart-Wechsel die Fachlogik nicht berührt.</para>
    /// </summary>
    public sealed class DashboardChartsModel : INotifyPropertyChanged
    {
        private static readonly SKColor Accent = new(0x1E, 0x88, 0xE5);
        private static readonly SKColor Positive = new(0x2E, 0x7D, 0x32);
        private static readonly SKColor Negative = new(0xC6, 0x28, 0x28);

        private ISeries[] _equitySeries = Array.Empty<ISeries>();
        private ISeries[] _moduleSeries = Array.Empty<ISeries>();
        private ISeries[] _daySeries = Array.Empty<ISeries>();
        private Axis[] _equityXAxes = Array.Empty<Axis>();
        private Axis[] _moduleXAxes = Array.Empty<Axis>();
        private Axis[] _dayXAxes = Array.Empty<Axis>();

        public ISeries[] EquitySeries { get => _equitySeries; private set => Set(ref _equitySeries, value); }
        public ISeries[] ModuleSeries { get => _moduleSeries; private set => Set(ref _moduleSeries, value); }
        public ISeries[] DaySeries { get => _daySeries; private set => Set(ref _daySeries, value); }
        public Axis[] EquityXAxes { get => _equityXAxes; private set => Set(ref _equityXAxes, value); }
        public Axis[] ModuleXAxes { get => _moduleXAxes; private set => Set(ref _moduleXAxes, value); }
        public Axis[] DayXAxes { get => _dayXAxes; private set => Set(ref _dayXAxes, value); }

        /// <summary>Baut alle drei Diagramme aus dem gefilterten Trade-Satz neu auf.</summary>
        public void Update(IReadOnlyList<TradeRecord> scoped)
        {
            BuildEquity(scoped);
            BuildByModule(scoped);
            BuildByDay(scoped);
        }

        private void BuildEquity(IReadOnlyList<TradeRecord> scoped)
        {
            var curve = TradeAnalytics.EquityCurve(scoped);

            EquitySeries = new ISeries[]
            {
                new LineSeries<DateTimePoint>
                {
                    Name = "Kumulierter PnL",
                    Values = curve.Select(p => new DateTimePoint(p.At, (double)p.Cumulative)).ToArray(),
                    Stroke = new SolidColorPaint(Accent, 2),
                    GeometrySize = 0,          // reine Linie – bei vielen Trades sonst unruhig
                    Fill = null
                }
            };

            EquityXAxes = new[]
            {
                new Axis
                {
                    // Ticks kommen als DateTime-Ticks – zurueckrechnen und kurz formatieren.
                    Labeler = value => new DateTime((long)value).ToString("dd.MM."),
                    UnitWidth = TimeSpan.FromDays(1).Ticks,
                    LabelsRotation = 0
                }
            };
        }

        private void BuildByModule(IReadOnlyList<TradeRecord> scoped)
        {
            var byMod = TradeAnalytics.PnlByKey(scoped,
                t => string.IsNullOrEmpty(t.ModuleName) ? "—" : t.ModuleName);

            ModuleSeries = new ISeries[]
            {
                new ColumnSeries<double>
                {
                    Name = "PnL",
                    Values = byMod.Select(x => (double)x.Pnl).ToArray(),
                    Fill = new SolidColorPaint(Accent)
                }
            };
            ModuleXAxes = new[] { new Axis { Labels = byMod.Select(x => x.Key).ToArray(), LabelsRotation = 0 } };
        }

        private void BuildByDay(IReadOnlyList<TradeRecord> scoped)
        {
            var byDay = TradeAnalytics.PnlByDay(scoped);

            DaySeries = new ISeries[]
            {
                new ColumnSeries<double>
                {
                    Name = "PnL",
                    Values = byDay.Select(x => (double)x.Pnl).ToArray(),
                    // Verlusttage rot, Gewinntage gruen – dieselbe Leseweise wie in den Trade-Listen.
                    Fill = new SolidColorPaint(byDay.Sum(x => x.Pnl) >= 0m ? Positive : Negative)
                }
            };
            DayXAxes = new[]
            {
                new Axis
                {
                    Labels = byDay.Select(x => x.Day.ToString("dd.MM")).ToArray(),
                    LabelsRotation = byDay.Count > 20 ? 45 : 0   // bei vielen Tagen sonst unleserlich
                }
            };
        }

        private void Set<T>(ref T field, T value, [CallerMemberName] string? name = null)
        {
            field = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

        public event PropertyChangedEventHandler? PropertyChanged;
    }
}
