using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Predictalytics.Application.Interfaces;
using Predictalytics.Domain.Entities;
using Predictalytics.Domain.Enums;
using Predictalytics.Domain.Interfaces;

namespace Predictalytics.Application.Services;

public class AiStrategyAnalysisService : IAiStrategyAnalysisService
{
    private readonly ITraderRepository _traderRepo;
    private readonly ITradeRepository _tradeRepo;
    private readonly IOpenRouterApiClient _openRouter;
    private readonly ILogger<AiStrategyAnalysisService> _logger;

    public AiStrategyAnalysisService(
        ITraderRepository traderRepo,
        ITradeRepository tradeRepo,
        IOpenRouterApiClient openRouter,
        ILogger<AiStrategyAnalysisService> logger)
    {
        _traderRepo = traderRepo;
        _tradeRepo = tradeRepo;
        _openRouter = openRouter;
        _logger = logger;
    }

    public async Task<string> AnalyzeTraderStrategyAsync(int traderId, bool manual, CancellationToken ct = default)
    {
        var trader = await _traderRepo.GetByIdAsync(traderId, ct);
        if (trader == null) return "Trader not found.";

        var trades = await _tradeRepo.GetByTraderIdAsync(traderId, 0, 500, ct);
        
        var prompt = BuildTraderContext(trader, trades);
        
        _logger.LogInformation("Sending {Model} AI analysis request for trader {TraderName}", manual ? "Manual (Claude)" : "Auto (Gemini)", trader.DisplayName);
        
        var jsonResult = await _openRouter.GenerateChatCompletionAsync(prompt, manual, ct);
        
        try 
        {
            // Remove markdown code blocks if present
            var cleanJson = jsonResult.Replace("```json", "").Replace("```", "").Trim();
            var parsed = JsonSerializer.Deserialize<JsonElement>(cleanJson);
            
            var summary = parsed.GetProperty("summary").GetString() ?? "No summary generated.";
            var strategyStr = parsed.GetProperty("strategy").GetString() ?? "Unknown";
            var isBot = parsed.GetProperty("isSuspectedBot").GetBoolean();
            
            if (Enum.TryParse<StrategyType>(strategyStr, true, out var strategy))
            {
                trader.Strategy = strategy;
            }
            trader.IsSuspectedBot = isBot;
            trader.AiStrategySummary = summary;
            trader.AiStrategyUpdatedAt = DateTime.UtcNow;
            
            await _traderRepo.UpdateAsync(trader, ct);
            return summary;
        } 
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to parse AI response for trader {TraderId}. Raw response: {Response}", traderId, jsonResult);
            return "Analysis failed to parse.";
        }
    }

    private string BuildTraderContext(Trader trader, IReadOnlyList<Trade> trades)
    {
        var sb = new StringBuilder();
        sb.AppendLine("Analyze the following prediction market trader.");
        sb.AppendLine($"Name: {trader.DisplayName}");
        sb.AppendLine($"Platform: {trader.Platform}");
        sb.AppendLine($"Total PnL: ${trader.TotalPnl:F2}");
        sb.AppendLine($"Win Rate: {trader.WinRate:F2}%");
        sb.AppendLine($"Total Trades: {trader.TotalTrades}");
        if (trader.Traits != null && trader.Traits.Count > 0)
        {
            sb.AppendLine("Algorithmic Traits (Heuristics):");
            foreach (var trait in trader.Traits)
            {
                sb.AppendLine($"- {trait.Trait} (Value: {trait.Value:F4})");
            }
        }
        sb.AppendLine();
        
        sb.AppendLine("Recent Trades:");
        foreach (var trade in trades.OrderByDescending(t => t.ExecutedAt).Take(50))
        {
            var marketQuestion = trade.DbMarket?.Question ?? "Unknown Market";
            var category = trade.DbMarket?.Category.ToString() ?? "Unknown";
            sb.AppendLine($"- {trade.ExecutedAt:yyyy-MM-dd}: {trade.Side} {trade.Size:F0} shares of '{trade.Outcome}' @ ${trade.Price:F2} (Total: ${trade.Amount:F2}) in [{category}] {marketQuestion}");
        }
        
        sb.AppendLine();
        sb.AppendLine("Based on these stats and recent trades, provide a concise summary of their strategy. Highlight their main strengths and weaknesses.");
        sb.AppendLine();
        sb.AppendLine("Classify their strategy into exactly one of the following categories:");
        sb.AppendLine("1. Scalper: High frequency, low hold time, takes small profits quickly.");
        sb.AppendLine("2. SwingTrader: Holds positions for days/weeks to capture large trends.");
        sb.AppendLine("3. Whale: Takes massive position sizes that move the market.");
        sb.AppendLine("4. Hedger: Takes opposing positions to minimize risk.");
        sb.AppendLine("5. Contrarian: Bets against the crowd or against prevailing momentum.");
        sb.AppendLine("6. MomentumTrader: Buys into strong trends and rides them.");
        sb.AppendLine("7. Arbitrageur: Exploits price differences across related outcomes/markets.");
        sb.AppendLine("8. Bot: Extremely high frequency, tiny sizes, robotic timing patterns.");
        sb.AppendLine("9. Unknown: If none apply.");
        sb.AppendLine();
        sb.AppendLine("OUTPUT FORMAT (JSON only, no markdown):");
        sb.AppendLine("{");
        sb.AppendLine("  \"summary\": \"Concise < 100 words text\",");
        sb.AppendLine("  \"strategy\": \"Scalper|SwingTrader|Whale|Hedger|Contrarian|MomentumTrader|Arbitrageur|Bot|Unknown\",");
        sb.AppendLine("  \"isSuspectedBot\": true/false");
        sb.AppendLine("}");
        
        return sb.ToString();
    }
}
