using System;
using System.Collections.Generic;
using System.Linq;
using NT8.Core.Intelligence;
using NT8.Core.Logging;

namespace NT8.Core.Analytics
{
    /// <summary>
    /// Regime transition impact summary.
    /// </summary>
    public class RegimeTransitionImpact
    {
        public string FromRegime { get; set; }
        public string ToRegime { get; set; }
        public int TradeCount { get; set; }
        public double TotalPnL { get; set; }
        public double AvgPnL { get; set; }
    }

    /// <summary>
    /// Regime performance report.
    /// </summary>
    public class RegimePerformanceReport
    {
        public Dictionary<string, PerformanceMetrics> CombinedMetrics { get; set; }
        public Dictionary<VolatilityRegime, PerformanceMetrics> VolatilityMetrics { get; set; }
        public Dictionary<TrendRegime, PerformanceMetrics> TrendMetrics { get; set; }
        public List<RegimeTransitionImpact> TransitionImpacts { get; set; }

        public RegimePerformanceReport()
        {
            CombinedMetrics = new Dictionary<string, PerformanceMetrics>();
            VolatilityMetrics = new Dictionary<VolatilityRegime, PerformanceMetrics>();
            TrendMetrics = new Dictionary<TrendRegime, PerformanceMetrics>();
            TransitionImpacts = new List<RegimeTransitionImpact>();
        }
    }

    /// <summary>
    /// Analyzer for volatility and trend regime trade outcomes.
    /// </summary>
    public class RegimePerformanceAnalyzer
    {
        private readonly ILogger _logger;
        private readonly PerformanceCalculator _calculator;

        public RegimePerformanceAnalyzer(ILogger logger)
        {
            if (logger == null)
                throw new ArgumentNullException("logger");

            _logger = logger;
            _calculator = new PerformanceCalculator(logger);
        }

        /// <summary>
        /// Produces report by individual and combined regimes.
        /// </summary>
        public RegimePerformanceReport AnalyzeByRegime(List<TradeRecord> trades)
        {
            if (trades == null)
                throw new ArgumentNullException("trades");

            try
            {
                var report = new RegimePerformanceReport();

                foreach (VolatilityRegime vol in Enum.GetValues(typeof(VolatilityRegime)))
                {
                    var subset = trades.Where(t => t.VolatilityRegime == vol).ToList();
                    report.VolatilityMetrics[vol] = _calculator.Calculate(subset);
                }

                foreach (TrendRegime trend in Enum.GetValues(typeof(TrendRegime)))
                {
                    var subset = trades.Where(t => t.TrendRegime == trend).ToList();
                    report.TrendMetrics[trend] = _calculator.Calculate(subset);
                }

                var combined = trades.GroupBy(t => string.Format("{0}|{1}", t.VolatilityRegime, t.TrendRegime));
                foreach (var group in combined)
                {
                    report.CombinedMetrics[group.Key] = _calculator.Calculate(group.ToList());
                }

                report.TransitionImpacts = AnalyzeTransitions(trades);
                return report;
            }
            catch (Exception ex)
            {
                _logger.LogError("AnalyzeByRegime failed: {0}", ex.Message);
                throw;
            }
        }

        /// <summary>
        /// Gets performance for one specific regime combination.
        /// </summary>
        public PerformanceMetrics GetPerformance(VolatilityRegime volRegime, TrendRegime trendRegime, List<TradeRecord> trades)
        {
            if (trades == null)
                throw new ArgumentNullException("trades");

            try
            {
                var subset = trades.Where(t => t.VolatilityRegime == volRegime && t.TrendRegime == trendRegime).ToList();
                return _calculator.Calculate(subset);
            }
            catch (Exception ex)
            {
                _logger.LogError("GetPerformance failed: {0}", ex.Message);
                throw;
            }
        }

        /// <summary>
        /// Analyzes regime transitions between consecutive trades.
        /// </summary>
        public List<RegimeTransitionImpact> AnalyzeTransitions(List<TradeRecord> trades)
        {
            if (trades == null)
                throw new ArgumentNullException("trades");

            try
            {
                var ordered = trades.OrderBy(t => t.EntryTime).ToList();
                var transitionPnl = new Dictionary<string, List<double>>();

                for (var i = 1; i < ordered.Count; i++)
                {
                    var from = string.Format("{0}|{1}", ordered[i - 1].VolatilityRegime, ordered[i - 1].TrendRegime);
                    var to = string.Format("{0}|{1}", ordered[i].VolatilityRegime, ordered[i].TrendRegime);
                    var key = string.Format("{0}->{1}", from, to);

                    if (!transitionPnl.ContainsKey(key))
                        transitionPnl.Add(key, new List<double>());
                    transitionPnl[key].Add(ordered[i].RealizedPnL);
                }

                var result = new List<RegimeTransitionImpact>();
                foreach (var kvp in transitionPnl)
                {
                    var parts = kvp.Key.Split(new[] {"->"}, StringSplitOptions.None);
                    var impact = new RegimeTransitionImpact();
                    impact.FromRegime = parts[0];
                    impact.ToRegime = parts.Length > 1 ? parts[1] : string.Empty;
                    impact.TradeCount = kvp.Value.Count;
                    impact.TotalPnL = kvp.Value.Sum();
                    impact.AvgPnL = kvp.Value.Count > 0 ? kvp.Value.Average() : 0.0;
                    result.Add(impact);
                }

                return result.OrderByDescending(r => r.TotalPnL).ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError("AnalyzeTransitions failed: {0}", ex.Message);
                throw;
            }
        }
    }
}
