/**
 * Bonus Rounds System
 * Manages interactive bonus games triggered by scatter symbols
 */

import { eq } from 'drizzle-orm';
import { getDb } from './db.ts';
import { users } from '../drizzle/schema.ts';

export type BonusType = 'pick-em' | 'wheel-spin' | 'free-spins' | 'multiplier' | 'mystery-box';

export interface BonusRound {
  id: string;
  userId: number;
  gameId: string;
  bonusType: BonusType;
  triggerAmount: number;
  multiplier: number;
  freeSpins: number;
  prize: number;
  completed: boolean;
  startedAt: Date;
  completedAt?: Date;
}

export interface PickEmBonus {
  type: 'pick-em';
  itemCount: number;
  selectedItems: number[];
  prizes: number[];
  totalPrize: number;
}

export interface WheelSpinBonus {
  type: 'wheel-spin';
  segments: number;
  selectedSegment: number;
  prize: number;
  multiplier: number;
}

export interface FreeSpinsBonus {
  type: 'free-spins';
  freeSpins: number;
  multiplier: number;
  totalPrize: number;
}

export interface MultiplierBonus {
  type: 'multiplier';
  multiplier: number;
  duration: number;
  prize: number;
}

export interface MysteryBoxBonus {
  type: 'mystery-box';
  boxCount: number;
  selectedBoxes: number[];
  prizes: number[];
  totalPrize: number;
}

/**
 * Trigger bonus round based on game result
 */
export async function triggerBonusRound(
  userId: number,
  gameId: string,
  scatterCount: number,
  triggerAmount: number
): Promise<BonusRound | null> {
  // Determine bonus type based on scatter count
  let bonusType: BonusType;
  let multiplier = 1;
  let freeSpins = 0;

  if (scatterCount >= 5) {
    bonusType = 'pick-em';
    multiplier = 3;
  } else if (scatterCount === 4) {
    bonusType = 'wheel-spin';
    multiplier = 2;
  } else if (scatterCount === 3) {
    bonusType = 'free-spins';
    freeSpins = 10;
    multiplier = 1.5;
  } else {
    return null; // No bonus triggered
  }

  const bonusId = `bonus_${userId}_${Date.now()}`;
  const prize = triggerAmount * multiplier;

  const bonus: BonusRound = {
    id: bonusId,
    userId,
    gameId,
    bonusType,
    triggerAmount,
    multiplier,
    freeSpins,
    prize,
    completed: false,
    startedAt: new Date(),
  };

  return bonus;
}

/**
 * Process pick-em bonus selection
 */
export function processPickEm(itemCount: number, selectedItems: number[]): PickEmBonus {
  const prizes = generatePrizes(itemCount);
  let totalPrize = 0;

  for (const index of selectedItems) {
    if (index >= 0 && index < prizes.length) {
      totalPrize += prizes[index];
    }
  }

  return {
    type: 'pick-em',
    itemCount,
    selectedItems,
    prizes,
    totalPrize,
  };
}

/**
 * Process wheel spin bonus
 */
export function processWheelSpin(segments: number, selectedSegment: number, baseMultiplier: number): WheelSpinBonus {
  const prizes = generateWheelPrizes(segments);
  const prize = prizes[selectedSegment] || 0;
  const multiplier = baseMultiplier * (1 + selectedSegment * 0.1);

  return {
    type: 'wheel-spin',
    segments,
    selectedSegment,
    prize,
    multiplier,
  };
}

/**
 * Process free spins bonus
 */
export function processFreeSpins(freeSpins: number, baseMultiplier: number): FreeSpinsBonus {
  const multiplier = baseMultiplier * 1.5;
  const totalPrize = freeSpins * 10 * multiplier; // Estimate based on average spin

  return {
    type: 'free-spins',
    freeSpins,
    multiplier,
    totalPrize,
  };
}

/**
 * Process multiplier bonus
 */
export function processMultiplier(baseMultiplier: number, duration: number, baseAmount: number): MultiplierBonus {
  const multiplier = baseMultiplier * 2;
  const prize = baseAmount * multiplier;

  return {
    type: 'multiplier',
    multiplier,
    duration,
    prize,
  };
}

/**
 * Process mystery box bonus
 */
export function processMysteryBox(boxCount: number, selectedBoxes: number[]): MysteryBoxBonus {
  const prizes = generateMysteryBoxPrizes(boxCount);
  let totalPrize = 0;

  for (const index of selectedBoxes) {
    if (index >= 0 && index < prizes.length) {
      totalPrize += prizes[index];
    }
  }

  return {
    type: 'mystery-box',
    boxCount,
    selectedBoxes,
    prizes,
    totalPrize,
  };
}

/**
 * Generate random prizes for pick-em bonus
 */
function generatePrizes(count: number): number[] {
  const prizes: number[] = [];
  for (let i = 0; i < count; i++) {
    // Generate prizes between 10 and 100
    prizes.push(Math.floor(Math.random() * 90) + 10);
  }
  return prizes;
}

/**
 * Generate random prizes for wheel spin
 */
function generateWheelPrizes(segments: number): number[] {
  const prizes: number[] = [];
  for (let i = 0; i < segments; i++) {
    // Generate prizes between 5 and 200
    prizes.push(Math.floor(Math.random() * 195) + 5);
  }
  return prizes;
}

/**
 * Generate random prizes for mystery box
 */
function generateMysteryBoxPrizes(count: number): number[] {
  const prizes: number[] = [];
  for (let i = 0; i < count; i++) {
    // Generate prizes between 15 and 150
    prizes.push(Math.floor(Math.random() * 135) + 15);
  }
  return prizes;
}

/**
 * Calculate bonus payout
 */
export function calculateBonusPayout(bonus: BonusRound, result: any): number {
  let payout = 0;

  switch (bonus.bonusType) {
    case 'pick-em':
      payout = result.totalPrize || 0;
      break;
    case 'wheel-spin':
      payout = result.prize || 0;
      break;
    case 'free-spins':
      payout = result.totalPrize || 0;
      break;
    case 'multiplier':
      payout = result.prize || 0;
      break;
    case 'mystery-box':
      payout = result.totalPrize || 0;
      break;
  }

  return Math.round(payout * 100) / 100;
}

/**
 * Get bonus history for a player
 */
export async function getBonusHistory(userId: number, limit: number = 50): Promise<BonusRound[]> {
  // This would typically query a database table
  // For now, returning empty array as placeholder
  return [];
}

/**
 * Get bonus statistics for a player
 */
export async function getBonusStats(userId: number) {
  const history = await getBonusHistory(userId, 1000);

  if (history.length === 0) {
    return {
      totalBonuses: 0,
      completedBonuses: 0,
      totalBonusPayout: 0,
      averagePayout: 0,
      biggestBonus: 0,
      bonusByType: {},
    };
  }

  const completed = history.filter((b) => b.completed);
  const totalPayout = completed.reduce((sum, b) => sum + b.prize, 0);

  const bonusByType: Record<BonusType, number> = {
    'pick-em': 0,
    'wheel-spin': 0,
    'free-spins': 0,
    multiplier: 0,
    'mystery-box': 0,
  };

  for (const bonus of completed) {
    bonusByType[bonus.bonusType]++;
  }

  return {
    totalBonuses: history.length,
    completedBonuses: completed.length,
    totalBonusPayout: totalPayout,
    averagePayout: completed.length > 0 ? totalPayout / completed.length : 0,
    biggestBonus: Math.max(...completed.map((b) => b.prize), 0),
    bonusByType,
  };
}
