import { Injectable, Logger } from "@nestjs/common";
import { PrismaService } from "../../../database/prisma.service";

/**
 * Spor Toto Analitik Servisi
 * - Havuz dağılım hesabı (%25/%20/%20/%35)
 * - Expected Value (EV) hesabı
 * - Devir geçmişi ve trend analizi
 */
@Injectable()
export class TotoAnalyticsService {
  private readonly logger = new Logger(TotoAnalyticsService.name);

  constructor(private readonly prisma: PrismaService) {}

  /**
   * Havuz dağılımını hesapla
   * Spor Toto havuz dağılımı:
   * %35 → 15 bilen
   * %20 → 14 bilen
   * %20 → 13 bilen
   * %25 → 12 bilen
   */
  calculatePoolDistribution(totalPool: number): {
    pool15: number;
    pool14: number;
    pool13: number;
    pool12: number;
  } {
    return {
      pool15: totalPool * 0.35,
      pool14: totalPool * 0.2,
      pool13: totalPool * 0.2,
      pool12: totalPool * 0.25,
    };
  }

  /**
   * Expected Value hesaplama
   * EV = (Kazanma Olasılığı × Ödül) - Maliyet
   *
   * 15 maçın tamamını bilme olasılığı (hepsi tek tahmin):
   * P = (1/3)^15 ≈ 1/14,348,907
   */
  calculateEV(
    poolTotal: number,
    rolloverAmount: number,
    columnCost: number,
    columnCount: number,
  ): {
    totalPool: number;
    pool15: number;
    probWin15: number;
    ev15: number;
    totalCost: number;
    netEV: number;
  } {
    const effectivePool = poolTotal + rolloverAmount;
    const distribution = this.calculatePoolDistribution(effectivePool);

    // Basit olasılık: 1/3^15 (her maç bağımsız, 3 sonuç)
    const probSingleColumn = 1 / Math.pow(3, 15); // ~6.97e-8
    const probWin15 = 1 - Math.pow(1 - probSingleColumn, columnCount);

    const totalCost = columnCost * columnCount;
    const ev15 = probWin15 * distribution.pool15 - totalCost;

    return {
      totalPool: effectivePool,
      pool15: distribution.pool15,
      probWin15,
      ev15,
      totalCost,
      netEV: ev15,
    };
  }

  /**
   * Devir geçmişi ve trend analizi
   */
  async getRolloverHistory(limit = 10): Promise<{
    history: Array<{
      gameCycleNo: number;
      programName: string | null;
      poolTotal: number | null;
      rolloverAmount: number | null;
      winners15: number;
      prize15: number | null;
    }>;
    averageRollover: number;
    consecutiveRollovers: number;
  }> {
    const bulletins = await this.prisma.totoBulletin.findMany({
      where: { status: "COMPLETED" },
      orderBy: { gameCycleNo: "desc" },
      take: limit,
      include: { result: true },
    });

    const history = bulletins.map((b) => ({
      gameCycleNo: b.gameCycleNo,
      programName: b.programName,
      poolTotal: b.poolTotal,
      rolloverAmount: b.rolloverAmount,
      winners15: b.result?.winners15 ?? 0,
      prize15: b.result?.prize15 ?? null,
    }));

    // Ortalama devir miktarı
    const rollovers = history
      .map((h) => h.rolloverAmount ?? 0)
      .filter((r) => r > 0);
    const averageRollover =
      rollovers.length > 0
        ? rollovers.reduce((a, b) => a + b, 0) / rollovers.length
        : 0;

    // Ardışık devir sayısı (son kaç haftadır devir var)
    let consecutiveRollovers = 0;
    for (const h of history) {
      if (h.winners15 === 0) {
        consecutiveRollovers++;
      } else {
        break;
      }
    }

    return { history, averageRollover, consecutiveRollovers };
  }

  /**
   * Bülten istatistikleri
   */
  async getBulletinStats(bulletinId: string): Promise<{
    poolDistribution: {
      pool15: number;
      pool14: number;
      pool13: number;
      pool12: number;
    } | null;
    ev: {
      totalPool: number;
      pool15: number;
      probWin15: number;
      ev15: number;
      totalCost: number;
      netEV: number;
    } | null;
    rolloverInfo: { averageRollover: number; consecutiveRollovers: number };
  }> {
    const bulletin = await this.prisma.totoBulletin.findUnique({
      where: { id: bulletinId },
    });

    if (!bulletin) {
      return {
        poolDistribution: null,
        ev: null,
        rolloverInfo: { averageRollover: 0, consecutiveRollovers: 0 },
      };
    }

    const poolDistribution = bulletin.poolTotal
      ? this.calculatePoolDistribution(
          bulletin.poolTotal + (bulletin.rolloverAmount ?? 0),
        )
      : null;

    const ev =
      bulletin.poolTotal != null
        ? this.calculateEV(
            bulletin.poolTotal,
            bulletin.rolloverAmount ?? 0,
            1, // birim fiyat
            1, // tek kolon bazında
          )
        : null;

    const rolloverInfo = await this.getRolloverHistory(20);

    return {
      poolDistribution,
      ev,
      rolloverInfo: {
        averageRollover: rolloverInfo.averageRollover,
        consecutiveRollovers: rolloverInfo.consecutiveRollovers,
      },
    };
  }
}
