import { Injectable, Logger } from "@nestjs/common";
import { HttpService } from "@nestjs/axios";
import { ConfigService } from "@nestjs/config";
import { PrismaService } from "../../../database/prisma.service";
import { firstValueFrom } from "rxjs";
import {
  TotoCombinatoricsService,
  TotoMatchSelectionInput,
} from "./toto-combinatorics.service";
import { TotoAnalyticsService } from "./toto-analytics.service";

// ═══════════ TYPES ═══════════

export type PredictionStrategy =
  | "CONSERVATIVE"
  | "BALANCED"
  | "AGGRESSIVE"
  | "FORMULA_6PCT";

export type TotoSelection = "1" | "X" | "2";

export interface MatchPredictionAnalysis {
  matchOrder: number;
  homeTeam: string;
  awayTeam: string;
  leagueName: string | null;
  /** Linked matchId from DB (null if not found) */
  linkedMatchId: string | null;
  /** AI Engine prediction source */
  predictionSource: "AI_ENGINE" | "HISTORICAL_FORM" | "FALLBACK";
  /** Raw AI probabilities for each outcome */
  probabilities: { home: number; draw: number; away: number };
  /** AI confidence (0-100) */
  confidence: number;
  /** AI's primary pick */
  aiPick: TotoSelection;
  /** Contrarian-adjusted selections for the coupon */
  selections: TotoSelection[];
  /** Why this selection was made */
  reasoning: string;
  /** Contrarian score: how "against the public" this pick is (0-100) */
  contrarianScore: number;
}

export interface PredictionResult {
  bulletinId: string;
  gameCycleNo: number;
  strategy: PredictionStrategy;
  /** Per-match analysis */
  matchAnalyses: MatchPredictionAnalysis[];
  /** Generated coupon */
  coupon: {
    totalColumns: number;
    cost: number;
    maxCouponLimit: number;
    columns: string[];
  };
  /** EV report */
  evReport: {
    poolTotal: number;
    rolloverAmount: number;
    effectivePool: number;
    ev15: number;
    evPerColumn: number;
    recommendation: "PLAY" | "WAIT" | "HIGH_VALUE";
    recommendationReason: string;
  };
  /** System info */
  systemInfo: {
    singlePicks: number;
    doublePicks: number;
    triplePicks: number;
    formula: string;
  };
}

// ═══════════ STRATEGY CONFIGS ═══════════

interface StrategyConfig {
  maxColumns: number;
  /** Confidence threshold for single pick */
  singleThreshold: number;
  /** Confidence threshold for double pick (below this → triple) */
  doubleThreshold: number;
  /** Use formula reduction */
  useFormulaReduction: boolean;
  /** Formula sampling rate (e.g., 0.06 = %6) */
  formulaSamplingRate: number;
  /** Favor contrarian picks */
  contrarianBias: number;
}

const STRATEGY_CONFIGS: Record<PredictionStrategy, StrategyConfig> = {
  CONSERVATIVE: {
    maxColumns: 100,
    singleThreshold: 55,
    doubleThreshold: 35,
    useFormulaReduction: false,
    formulaSamplingRate: 1.0,
    contrarianBias: 0.0,
  },
  BALANCED: {
    maxColumns: 500,
    singleThreshold: 60,
    doubleThreshold: 40,
    useFormulaReduction: false,
    formulaSamplingRate: 1.0,
    contrarianBias: 0.15,
  },
  AGGRESSIVE: {
    maxColumns: 2500,
    singleThreshold: 70,
    doubleThreshold: 50,
    useFormulaReduction: false,
    formulaSamplingRate: 1.0,
    contrarianBias: 0.3,
  },
  FORMULA_6PCT: {
    maxColumns: 2500,
    singleThreshold: 60,
    doubleThreshold: 40,
    useFormulaReduction: true,
    formulaSamplingRate: 0.06,
    contrarianBias: 0.2,
  },
};

// ═══════════ SERVICE ═══════════

@Injectable()
export class TotoPredictionService {
  private readonly logger = new Logger(TotoPredictionService.name);
  private readonly aiEngineUrl: string;

  constructor(
    private readonly prisma: PrismaService,
    private readonly httpService: HttpService,
    private readonly configService: ConfigService,
    private readonly combinatorics: TotoCombinatoricsService,
    private readonly analytics: TotoAnalyticsService,
  ) {
    this.aiEngineUrl =
      this.configService.get("AI_ENGINE_URL") || "http://127.0.0.1:8000";
  }

  /**
   * Ana tahmin motoru: Bülten → AI analiz → Contrarian strateji → Sistem kuponu
   */
  async generatePrediction(
    bulletinId: string,
    strategy: PredictionStrategy = "BALANCED",
    maxBudget?: number,
  ): Promise<PredictionResult> {
    const config = STRATEGY_CONFIGS[strategy];

    // 1. Bülteni getir
    const bulletin = await this.prisma.totoBulletin.findUnique({
      where: { id: bulletinId },
      include: { matches: { orderBy: { matchOrder: "asc" } } },
    });

    if (!bulletin) {
      throw new Error(`Bulletin not found: ${bulletinId}`);
    }

    this.logger.log(
      `Generating prediction for Cycle ${bulletin.gameCycleNo} — Strategy: ${strategy}`,
    );

    // 2. Her maç için AI tahmin al
    const matchAnalyses: MatchPredictionAnalysis[] = [];

    for (const match of bulletin.matches) {
      const analysis = await this.analyzeMatch(
        match.matchOrder,
        match.homeTeamName,
        match.awayTeamName,
        match.leagueName,
        match.kickoffTime,
        match.matchId,
        config,
      );
      matchAnalyses.push(analysis);
    }

    // 3. Selections'dan kupon üret
    const matchSelections: TotoMatchSelectionInput[] = matchAnalyses.map(
      (a) => ({
        matchOrder: a.matchOrder,
        selections: a.selections,
      }),
    );

    const totalColumns =
      this.combinatorics.calculateColumnCount(matchSelections);

    // Bütçe kontrolü
    let effectiveMaxColumns = config.maxColumns;
    if (maxBudget && maxBudget < totalColumns) {
      effectiveMaxColumns = Math.min(effectiveMaxColumns, maxBudget);
    }

    // Kolon üretimi
    let columns;
    if (config.useFormulaReduction) {
      // Formula %6: Tam sistemden yüzde örnekleme
      const sampledCount = Math.max(
        1,
        Math.floor(totalColumns * config.formulaSamplingRate),
      );
      const targetCount = Math.min(sampledCount, effectiveMaxColumns);
      columns = this.combinatorics.generateReducedSystem(
        matchSelections,
        targetCount,
      );
    } else if (totalColumns > effectiveMaxColumns) {
      columns = this.combinatorics.generateReducedSystem(
        matchSelections,
        effectiveMaxColumns,
      );
    } else {
      columns = this.combinatorics.generateFullSystem(matchSelections);
    }

    const cost = this.combinatorics.calculateCost(columns.length);

    // 4. EV raporu
    const evReport = await this.calculateEvReport(
      bulletin.poolTotal ?? 0,
      bulletin.rolloverAmount ?? 0,
      columns.length,
      cost,
    );

    // 5. Sistem bilgisi
    const singles = matchAnalyses.filter(
      (a) => a.selections.length === 1,
    ).length;
    const doubles = matchAnalyses.filter(
      (a) => a.selections.length === 2,
    ).length;
    const triples = matchAnalyses.filter(
      (a) => a.selections.length === 3,
    ).length;

    return {
      bulletinId: bulletin.id,
      gameCycleNo: bulletin.gameCycleNo,
      strategy,
      matchAnalyses,
      coupon: {
        totalColumns: columns.length,
        cost,
        maxCouponLimit: 2500,
        columns: columns.map((c) => c.predictions),
      },
      evReport,
      systemInfo: {
        singlePicks: singles,
        doublePicks: doubles,
        triplePicks: triples,
        formula: `2^${doubles} × 3^${triples} = ${totalColumns} (full) → ${columns.length} (generated)`,
      },
    };
  }

  // ═══════════ MATCH ANALYSIS ═══════════

  /**
   * Tek bir maç için AI tahmin + contrarian analiz
   */
  private async analyzeMatch(
    matchOrder: number,
    homeTeam: string,
    awayTeam: string,
    leagueName: string | null,
    kickoffTime: Date | null,
    existingMatchId: string | null,
    config: StrategyConfig,
  ): Promise<MatchPredictionAnalysis> {
    // 1. Match linking — DB'den matchId bul
    const linkedMatchId =
      existingMatchId ||
      (await this.fuzzyMatchLink(homeTeam, awayTeam, kickoffTime));

    // 2. AI Engine'den tahmin al
    let probabilities = { home: 0.33, draw: 0.33, away: 0.34 };
    let confidence = 33;
    let aiPick: TotoSelection = "1";
    let predictionSource: MatchPredictionAnalysis["predictionSource"] =
      "FALLBACK";
    let reasoning = "Eşleşme bulunamadı, eşit dağılım kullanıldı";

    if (linkedMatchId) {
      const aiResult = await this.callAiEngine(linkedMatchId);

      if (aiResult) {
        probabilities = aiResult.probabilities;
        confidence = aiResult.confidence;
        aiPick = aiResult.pick;
        predictionSource = "AI_ENGINE";
        reasoning = aiResult.reasoning;
      } else {
        // AI Engine erişilemez → tarihsel form analizi
        const formResult = await this.analyzeHistoricalForm(homeTeam, awayTeam);
        probabilities = formResult.probabilities;
        confidence = formResult.confidence;
        aiPick = formResult.pick;
        predictionSource = "HISTORICAL_FORM";
        reasoning = formResult.reasoning;
      }
    } else {
      // matchId yok → tarihsel form analizi dene
      const formResult = await this.analyzeHistoricalForm(homeTeam, awayTeam);
      if (formResult.confidence > 33) {
        probabilities = formResult.probabilities;
        confidence = formResult.confidence;
        aiPick = formResult.pick;
        predictionSource = "HISTORICAL_FORM";
        reasoning = formResult.reasoning;
      }
    }

    // 3. Contrarian strateji — maç seçimleri belirle
    const { selections, contrarianScore, contrarianReasoning } =
      this.applyContrarianStrategy(probabilities, confidence, aiPick, config);

    return {
      matchOrder,
      homeTeam,
      awayTeam,
      leagueName,
      linkedMatchId,
      predictionSource,
      probabilities,
      confidence,
      aiPick,
      selections,
      reasoning: `${reasoning} | ${contrarianReasoning}`,
      contrarianScore,
    };
  }

  // ═══════════ FUZZY MATCH LINKING ═══════════

  /**
   * Bülten maç adlarını DB'deki live_matches/matches ile eşleştir
   * Strateji: takım adlarını normalize et, ILIKE ile ara, tarih filtrele
   */
  private async fuzzyMatchLink(
    homeTeam: string,
    awayTeam: string,
    kickoffTime: Date | null,
  ): Promise<string | null> {
    const homeNorm = this.normalizeTeamName(homeTeam);
    const awayNorm = this.normalizeTeamName(awayTeam);

    // 1. Önce live_matches'te ara (canlı + odds verisi var)
    try {
      const liveMatch = await this.prisma.$queryRawUnsafe<
        Array<{ id: string }>
      >(
        `SELECT id FROM live_matches 
         WHERE LOWER(match_name) LIKE $1 AND LOWER(match_name) LIKE $2
         ${kickoffTime ? `AND ABS(CAST(mst_utc AS BIGINT) - $3) < 259200000` : ""}
         LIMIT 1`,
        `%${homeNorm}%`,
        `%${awayNorm}%`,
        ...(kickoffTime ? [kickoffTime.getTime()] : []),
      );

      if (liveMatch.length > 0) {
        this.logger.debug(
          `Fuzzy matched live: ${homeTeam} vs ${awayTeam} → ${liveMatch[0].id}`,
        );
        return liveMatch[0].id;
      }
    } catch (err) {
      this.logger.warn(`Live match fuzzy search failed: ${err}`);
    }

    // 2. matches tablosunda ara (tarihsel)
    try {
      const match = await this.prisma.$queryRawUnsafe<Array<{ id: string }>>(
        `SELECT id FROM matches 
         WHERE LOWER(match_name) LIKE $1 AND LOWER(match_name) LIKE $2
         ${kickoffTime ? `AND ABS(CAST(mst_utc AS BIGINT) - $3) < 259200000` : ""}
         ORDER BY mst_utc DESC
         LIMIT 1`,
        `%${homeNorm}%`,
        `%${awayNorm}%`,
        ...(kickoffTime ? [kickoffTime.getTime()] : []),
      );

      if (match.length > 0) {
        this.logger.debug(
          `Fuzzy matched historical: ${homeTeam} vs ${awayTeam} → ${match[0].id}`,
        );
        return match[0].id;
      }
    } catch (err) {
      this.logger.warn(`Historical match fuzzy search failed: ${err}`);
    }

    this.logger.warn(`No match found for: ${homeTeam} vs ${awayTeam}`);
    return null;
  }

  /**
   * Takım adını normalize et (lowercase, türkçe karakter düzelt, boşlukları trim)
   */
  private normalizeTeamName(name: string): string {
    return name
      .toLowerCase()
      .trim()
      .replace(/ı/g, "i")
      .replace(/ğ/g, "g")
      .replace(/ü/g, "u")
      .replace(/ş/g, "s")
      .replace(/ö/g, "o")
      .replace(/ç/g, "c")
      .replace(/\./g, "")
      .replace(/\s+/g, " ");
  }

  // ═══════════ AI ENGINE INTEGRATION ═══════════

  /**
   * AI Engine V20+ ile maç analizi
   */
  private async callAiEngine(matchId: string): Promise<{
    probabilities: { home: number; draw: number; away: number };
    confidence: number;
    pick: TotoSelection;
    reasoning: string;
  } | null> {
    try {
      const response = await firstValueFrom(
        this.httpService.post(
          `${this.aiEngineUrl}/v20plus/analyze/${matchId}`,
          {},
          { timeout: 30000 },
        ),
      );

      const data = response.data;
      if (!data || !data.bet_summary) {
        return null;
      }

      // "Maç Sonucu" market'ını bul
      const msPick = (
        data.bet_summary as Array<{
          market: string;
          pick: string;
          calibrated_confidence?: number;
          confidence?: number;
          probability?: number;
          reasons?: string[];
        }>
      ).find(
        (b) =>
          b.market?.toLowerCase().includes("maç sonucu") ||
          b.market?.toLowerCase().includes("match result") ||
          b.market === "1X2",
      );

      // Score prediction'dan olasılıklar çıkar
      const scorePred = data.score_prediction;
      let probabilities = { home: 0.4, draw: 0.3, away: 0.3 };

      if (scorePred?.xg_home != null && scorePred?.xg_away != null) {
        // xG bazlı basit olasılık tahmini
        const xgHome = scorePred.xg_home;
        const xgAway = scorePred.xg_away;
        const total = xgHome + xgAway + 0.001;
        const homeStrength = xgHome / total;
        const awayStrength = xgAway / total;

        probabilities = {
          home: Math.max(0.1, Math.min(0.8, homeStrength + 0.1)),
          draw: Math.max(
            0.1,
            Math.min(0.4, 1 - Math.abs(homeStrength - awayStrength)),
          ),
          away: Math.max(0.1, Math.min(0.8, awayStrength)),
        };

        // Normalize
        const sum =
          probabilities.home + probabilities.draw + probabilities.away;
        probabilities.home /= sum;
        probabilities.draw /= sum;
        probabilities.away /= sum;
      }

      // Pick'i Toto formatına çevir
      let pick: TotoSelection = "1";
      if (msPick) {
        const rawPick = msPick.pick?.toLowerCase();
        if (
          rawPick?.includes("2") ||
          rawPick?.includes("away") ||
          rawPick?.includes("deplasman")
        ) {
          pick = "2";
        } else if (
          rawPick?.includes("x") ||
          rawPick?.includes("draw") ||
          rawPick?.includes("beraberlik")
        ) {
          pick = "X";
        } else {
          pick = "1";
        }
      } else {
        // No explicit MS pick → use probabilities
        if (
          probabilities.away > probabilities.home &&
          probabilities.away > probabilities.draw
        ) {
          pick = "2";
        } else if (probabilities.draw > probabilities.home) {
          pick = "X";
        }
      }

      const confidence = Math.round(
        (msPick?.calibrated_confidence ?? msPick?.confidence ?? 50) *
          (typeof (msPick?.calibrated_confidence ?? msPick?.confidence) ===
            "number" &&
          (msPick?.calibrated_confidence ?? msPick?.confidence ?? 0) <= 1
            ? 100
            : 1),
      );

      const reasons = msPick?.reasons ?? [];

      return {
        probabilities,
        confidence,
        pick,
        reasoning:
          reasons.length > 0
            ? reasons.join(" | ")
            : `AI Engine: ${pick} (confidence: ${confidence}%)`,
      };
    } catch (error) {
      this.logger.warn(
        `AI Engine call failed for ${matchId}: ${error instanceof Error ? error.message : error}`,
      );
      return null;
    }
  }

  // ═══════════ HISTORICAL FORM ANALYSIS ═══════════

  /**
   * AI Engine erişilemezse: Tarihsel form bazlı basit olasılık hesabı
   * Son 10 maçın ev sahibi/deplasman performansını analiz eder
   */
  private async analyzeHistoricalForm(
    homeTeam: string,
    awayTeam: string,
  ): Promise<{
    probabilities: { home: number; draw: number; away: number };
    confidence: number;
    pick: TotoSelection;
    reasoning: string;
  }> {
    const homeNorm = this.normalizeTeamName(homeTeam);
    const awayNorm = this.normalizeTeamName(awayTeam);

    try {
      // Son 10 ev sahibi maçı
      const homeMatches = await this.prisma.$queryRawUnsafe<
        Array<{ winner: string | null }>
      >(
        `SELECT winner FROM matches 
         WHERE LOWER(match_name) LIKE $1 AND winner IS NOT NULL
         ORDER BY mst_utc DESC LIMIT 10`,
        `%${homeNorm}%`,
      );

      // Son 10 deplasman maçı
      const awayMatches = await this.prisma.$queryRawUnsafe<
        Array<{ winner: string | null }>
      >(
        `SELECT winner FROM matches 
         WHERE LOWER(match_name) LIKE $1 AND winner IS NOT NULL
         ORDER BY mst_utc DESC LIMIT 10`,
        `%${awayNorm}%`,
      );

      if (homeMatches.length === 0 && awayMatches.length === 0) {
        return {
          probabilities: { home: 0.33, draw: 0.33, away: 0.34 },
          confidence: 33,
          pick: "1",
          reasoning: "Tarihsel veri bulunamadı, eşit dağılım",
        };
      }

      // Ev sahibi form analizi
      const homeWins = homeMatches.filter((m) => m.winner === "home").length;
      const homeDraws = homeMatches.filter((m) => m.winner === "draw").length;
      const homeLosses = homeMatches.filter((m) => m.winner === "away").length;
      const homeTotal = homeMatches.length || 1;

      // Deplasman form analizi
      const awayWins = awayMatches.filter((m) => m.winner === "away").length;
      const awayDraws = awayMatches.filter((m) => m.winner === "draw").length;
      const awayLosses = awayMatches.filter((m) => m.winner === "home").length;
      const awayTotal = awayMatches.length || 1;

      // Basit form bazlı olasılık
      const homeProb =
        (homeWins / homeTotal) * 0.6 + (awayLosses / awayTotal) * 0.4;
      const drawProb =
        (homeDraws / homeTotal) * 0.5 + (awayDraws / awayTotal) * 0.5;
      const awayProb =
        (homeLosses / homeTotal) * 0.4 + (awayWins / awayTotal) * 0.6;

      // Normalize
      const sum = homeProb + drawProb + awayProb || 1;
      const probabilities = {
        home: homeProb / sum,
        draw: drawProb / sum,
        away: awayProb / sum,
      };

      // En yüksek olasılık
      let pick: TotoSelection = "1";
      if (
        probabilities.away > probabilities.home &&
        probabilities.away > probabilities.draw
      ) {
        pick = "2";
      } else if (probabilities.draw > probabilities.home) {
        pick = "X";
      }

      const confidence = Math.round(
        Math.max(probabilities.home, probabilities.draw, probabilities.away) *
          100,
      );

      return {
        probabilities,
        confidence,
        pick,
        reasoning: `Form: ${homeTeam} (${homeWins}W/${homeDraws}D/${homeLosses}L son ${homeTotal}) vs ${awayTeam} (${awayWins}W/${awayDraws}D/${awayLosses}L son ${awayTotal})`,
      };
    } catch (err) {
      this.logger.warn(`Historical form analysis failed: ${err}`);
      return {
        probabilities: { home: 0.33, draw: 0.33, away: 0.34 },
        confidence: 33,
        pick: "1",
        reasoning: "Form analizi yapılamadı, eşit dağılım",
      };
    }
  }

  // ═══════════ CONTRARIAN STRATEGY ═══════════

  /**
   * Parimutüel mantık: "Herkesin bildiğini bilmenin değeri yok"
   *
   * - Confidence yüksek + favori → public de aynı yöne oynar → düşük parimutüel değer
   * - Sürpriz potansiyeli olan maçlara çift/üçlü seçim → az kişi bilir → yüksek değer
   *
   * Contrarian bias: Favorinin çok güçlü olduğu durumda bile sürpriz ihtimalini
   * kupon içinde tutarak, varyansı kucaklamak (7. maçta Juventus'un evinde kaybetmesi gibi)
   */
  private applyContrarianStrategy(
    probabilities: { home: number; draw: number; away: number },
    confidence: number,
    aiPick: TotoSelection,
    config: StrategyConfig,
  ): {
    selections: TotoSelection[];
    contrarianScore: number;
    contrarianReasoning: string;
  } {
    // Olasılıkları sırala
    const probs: Array<{ pick: TotoSelection; prob: number }> = [
      { pick: "1" as TotoSelection, prob: probabilities.home },
      { pick: "X" as TotoSelection, prob: probabilities.draw },
      { pick: "2" as TotoSelection, prob: probabilities.away },
    ].sort((a, b) => b.prob - a.prob);

    const topProb = probs[0].prob;
    const secondProb = probs[1].prob;
    const gap = topProb - secondProb;

    // Contrarian score: Favori ne kadar belirginse, public o kadar yığılır
    // → bize ters yönü kapsamamız lazım
    const contrarianScore = Math.round(
      Math.min(100, (topProb * 100 - 33) * 2 + config.contrarianBias * 30),
    );

    // Karar: confidence ve strateji config'e göre
    let selections: TotoSelection[];
    let contrarianReasoning: string;

    if (confidence >= config.singleThreshold && gap > 0.2) {
      // Yüksek güven + belirgin fark → tek seçim (ama contrarian bias varsa %X ihtimal)
      if (
        config.contrarianBias > 0 &&
        topProb > 0.55 &&
        Math.random() < config.contrarianBias
      ) {
        // Contrarian: Favori + ikinci seçenek
        selections = [probs[0].pick, probs[1].pick];
        contrarianReasoning = `Contrarian çift: ${probs[0].pick}(${(probs[0].prob * 100).toFixed(0)}%) + ${probs[1].pick}(${(probs[1].prob * 100).toFixed(0)}%) — Public yığılma riski`;
      } else {
        selections = [probs[0].pick];
        contrarianReasoning = `Tek: ${probs[0].pick}(${(probs[0].prob * 100).toFixed(0)}%) — Yüksek güven`;
      }
    } else if (confidence >= config.doubleThreshold) {
      // Orta güven → ikili seçim (en olası 2)
      selections = [probs[0].pick, probs[1].pick];
      contrarianReasoning = `İkili: ${probs[0].pick} + ${probs[1].pick} — Orta güven, varyans koruması`;
    } else {
      // Düşük güven → üçlü kapatma
      selections = ["1", "X", "2"];
      contrarianReasoning = `Kapatma: 1X2 — Düşük güven (${confidence}%), maç çok belirsiz`;
    }

    return { selections, contrarianScore, contrarianReasoning };
  }

  // ═══════════ EV CALCULATION ═══════════

  /**
   * Expected Value raporu — Devir yüksekse oyna
   */
  private async calculateEvReport(
    poolTotal: number,
    rolloverAmount: number,
    columnCount: number,
    totalCost: number,
  ): Promise<PredictionResult["evReport"]> {
    const effectivePool = poolTotal + rolloverAmount;
    const distribution =
      this.analytics.calculatePoolDistribution(effectivePool);

    // Basit EV: (15 bilme olasılığı × havuz payı) - maliyet
    const prob15 = 1 / Math.pow(3, 15); // ~6.97e-8
    const probWinWithColumns = 1 - Math.pow(1 - prob15, columnCount);
    const ev15 = probWinWithColumns * distribution.pool15 - totalCost;
    const evPerColumn = columnCount > 0 ? ev15 / columnCount : 0;

    // Devir bilgisi
    let rolloverData;
    try {
      rolloverData = await this.analytics.getRolloverHistory(5);
    } catch {
      rolloverData = {
        consecutiveRollovers: 0,
        averageRollover: 0,
        history: [],
      };
    }

    // Karar
    let recommendation: PredictionResult["evReport"]["recommendation"];
    let recommendationReason: string;

    if (rolloverAmount > 50_000_000) {
      recommendation = "HIGH_VALUE";
      recommendationReason = `🔥 ${(rolloverAmount / 1_000_000).toFixed(1)}M TL devir! Tarihi fırsat. Agresif oyna.`;
    } else if (rolloverAmount > 20_000_000) {
      recommendation = "PLAY";
      recommendationReason = `✅ ${(rolloverAmount / 1_000_000).toFixed(1)}M TL devir. Oynamaya değer. (Ardışık ${rolloverData.consecutiveRollovers} hafta devir)`;
    } else if (rolloverAmount > 5_000_000) {
      recommendation = "PLAY";
      recommendationReason = `✅ Orta düzey devir: ${(rolloverAmount / 1_000_000).toFixed(1)}M TL`;
    } else {
      recommendation = "WAIT";
      recommendationReason = `⏳ Devir düşük (${(rolloverAmount / 1_000_000).toFixed(1)}M TL). Havuz büyümesini bekle.`;
    }

    return {
      poolTotal,
      rolloverAmount,
      effectivePool,
      ev15,
      evPerColumn,
      recommendation,
      recommendationReason,
    };
  }
}
