using System;
using PolyTrader.Modules.CopyTrading.Persistence;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using PolyTraderSharp.Models;

namespace PolyTraderSharp.Services
{
    public class TraderAnalyticsJob : BackgroundService
    {
        private readonly TradingState _state;
        private readonly CopyTradingState _copyState;
        private readonly TerminalLogger _logger;
        private readonly ICopyTradeLogRepository _tradeLog;
        private readonly JobStatusRow _jobStatus;

        public TraderAnalyticsJob(TradingState state, CopyTradingState copyState, TerminalLogger logger, ICopyTradeLogRepository tradeLog, JobManager jobManager)
        {
            _state = state;
            _copyState = copyState;
            _logger = logger;
            _tradeLog = tradeLog;

            _jobStatus = new JobStatusRow
            {
                JobName = "Trader Analytics",
                Description = "Analysiert Master-Trader-Performance pro Account (letzte 30 Trades, 7D Volumen).",
                StatusText = "Pending Initial Delay..."
            };

            _jobStatus.ManualTriggerAction = async () => 
            {
                _jobStatus.StatusText = "Running (Manual)...";
                await RunAnalyticsAsync();
                _jobStatus.StatusText = "Idle";
                _jobStatus.LastRun = DateTime.Now;
            };

            jobManager.RegisterJob(_jobStatus);
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            // Initial wait so the application can start smoothly
            await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);

            while (!stoppingToken.IsCancellationRequested)
            {
                if (_jobStatus.IsEnabled)
                {
                    try
                    {
                        _jobStatus.StatusText = "Running (Scheduled)...";
                        await RunAnalyticsAsync();
                        _jobStatus.LastRun = DateTime.Now;
                    }
                    catch (Exception ex)
                    {
                        _logger.Error($"Error in TraderAnalyticsJob: {ex.Message}");
                        _jobStatus.StatusText = "Error!";
                    }
                    finally
                    {
                        if (_jobStatus.StatusText != "Error!") _jobStatus.StatusText = "Idle";
                    }
                }
                else
                {
                    _jobStatus.StatusText = "Paused";
                }

                _jobStatus.NextRun = DateTime.Now.AddHours(6);
                await Task.Delay(TimeSpan.FromHours(6), stoppingToken);
            }
        }

        private Task RunAnalyticsAsync()
        {
            return Task.Run(() =>
            {
                try
                {
                    _logger.Info("🔄 Starte Trader Analytics (7D / Letzte 30 Trades)...");
                    
                    _tradeLog.EnsureIndexes();

                    DateTime sevenDaysAgo = DateTime.UtcNow.AddDays(-7);

                    foreach (var acc in _state.Accounts.Values)
                    {
                        var results = new List<TraderAnalyticsResult>();

                        // Find all master traders that this account has copied successfully in their entire history
                        // Or we just find MTs that were copied in the last 7 days? 
                        // The requirement says: "Welche Trades ... in den letzten 7 Tagen kopiert ... und wie hoch war die Winrate der letzten 30 Trades"
                        // Thus we only care about MTs that had at least 1 trade in the last 7 days!
                        int accId = acc.AccountId;
                        var recentMTs = _tradeLog.Find(x => x.AccountId == accId && x.ClosedAt >= sevenDaysAgo)
                                                        .Select(x => x.SourceTraderId)
                                                        .Distinct()
                                                        .Where(id => id != 0) // Ignore orphaned historical trades (API resolved/auto-redeem before ID tracking patch)
                                                        .ToList();

                        foreach (var mtId in recentMTs)
                        {
                            var mtInfo = _copyState.Traders.Values.FirstOrDefault(t => t.Id == mtId);
                            string name = mtInfo?.DisplayName ?? $"MT #{mtId}";
                            string address = mtInfo?.WalletAddress ?? "";

                            // 1. Trades im 7D Fenster zählen
                            int trades7D = _tradeLog.Find(x => x.AccountId == accId && x.SourceTraderId == mtId && x.ClosedAt >= sevenDaysAgo).Count();

                            // 2. Letzte 30 Trades holen
                            var last30 = _tradeLog.Find(x => x.AccountId == accId && x.SourceTraderId == mtId)
                                                         .OrderByDescending(x => x.ClosedAt)
                                                         .Take(30)
                                                         .ToList();

                            if (last30.Count == 0) continue;

                            decimal pnl30T = last30.Sum(x => x.RealizedPnl);
                            int wins = last30.Count(x => x.RealizedPnl > 0); 
                            // Exakt 0 ist kein Win, nur > 0
                            decimal winrate = ((decimal)wins / last30.Count) * 100m;

                            results.Add(new TraderAnalyticsResult
                            {
                                AccountId = acc.AccountId,
                                SourceTraderId = mtId,
                                SourceTraderName = name,
                                SourceTraderAddress = address,
                                Winrate30T = winrate,
                                Pnl30T = pnl30T,
                                Trades7D = trades7D
                            });
                        }

                        // Save to cache
                        _copyState.TraderAnalyticsCache[acc.AccountId] = results;
                    }
                    
                    _logger.Info("✅ Trader Analytics erfolgreich abgeschlossen und im Cache aktualisiert.");
                }
                catch (Exception ex)
                {
                    _logger.Error($"TraderAnalyticsJob Exception: {ex}");
                }
            });
        }
    }
}
