// ─── Discipline Math Utilities ────────────────────────────────────────────────
// Continuous scaling formulas for Active Disciplines

import type { DisciplineState, DisciplineDefinition, DisciplinePerk } from '../types/disciplines';

/**
 * Calculate continuous stat bonus from discipline XP
 * StatBonus = BaseValue * (XP / ScalingFactor)^0.65
 */
export function calculateStatBonus(
  baseValue: number,
  xp: number,
  scalingFactor: number
): number {
  if (xp <= 0) return 0;
  const ratio = xp / scalingFactor;
  const power = Math.pow(ratio, 0.65);
  return baseValue * power;
}

/**
 * Calculate dynamic mana drain per tick
 * ManaDrainPerTick = BaseDrain * (1 + (XP / DifficultyFactor)^0.4)
 */
export function calculateManaDrain(
  baseDrain: number,
  xp: number,
  difficultyFactor: number
): number {
  if (xp <= 0) return baseDrain;
  const ratio = xp / difficultyFactor;
  const power = Math.pow(ratio, 0.4);
  return baseDrain * (1 + power);
}

/**
 * Calculate infinite perk tier
 * PerkTier = Math.max(0, Math.floor((XP - Threshold) / Interval) + 1)
 */
export function calculatePerkTier(
  xp: number,
  threshold: number,
  interval: number
): number {
  if (xp < threshold) return 0;
  const excess = xp - threshold;
  return Math.max(0, Math.floor(excess / interval) + 1);
}

/**
 * Check if discipline can be activated (has required mana type)
 */
export function canActivateDiscipline(
  discipline: DisciplineDefinition,
  gameState: { elements?: Record<string, any> }
): boolean {
  if (discipline.manaType === 'raw') return true;
  const element = gameState.elements?.[discipline.manaType];
  return element && element.unlocked;
}

/**
 * Check if discipline can proceed (has sufficient mana for drain)
 */
export function canProceedDiscipline(
  discipline: DisciplineDefinition,
  disciplineState: DisciplineState | undefined,
  gameState?: { elements?: Record<string, any>; rawMana?: number }
): boolean {
  if (!disciplineState) return true;
  if (disciplineState.paused) return false;

  // If no game state provided, allow activation (optimistic)
  if (!gameState) return true;

  const drain = calculateManaDrain(
    discipline.drainBase,
    disciplineState.xp,
    discipline.difficultyFactor
  );

  if (discipline.manaType === 'raw') {
    return (gameState.rawMana || 0) >= drain;
  }

  const element = gameState.elements?.[discipline.manaType];
  return element && element.current >= drain;
}

/**
 * Get unlocked perks for a discipline
 */
export function getUnlockedPerks(
  discipline: DisciplineDefinition,
  xp: number
): DisciplinePerk[] {
  return discipline.perks.filter(perk => {
    if (perk.type === 'once') {
      return xp >= perk.threshold;
    } else if (perk.type === 'capped') {
      const tier = calculatePerkTier(xp, perk.threshold, perk.value);
      return tier > 0;
    } else if (perk.type === 'infinite') {
      return xp >= perk.threshold;
    }
    return false;
  });
}

/**
 * Calculate total stats from all active disciplines
 */
export function calculateDisciplineStats(
  disciplines: DisciplineDefinition[],
  states: DisciplineState[]
): Record<string, number> {
  const stats: Record<string, number> = {};
  
  disciplines.forEach((discipline, index) => {
    const state = states[index];
    if (!state || state.paused) return;
    
    const bonus = calculateStatBonus(
      discipline.statBonus.baseValue,
      state.xp,
      discipline.scalingFactor
    );
    
    const statKey = discipline.statBonus.stat;
    stats[statKey] = (stats[statKey] || 0) + bonus;
  });
  
  return stats;
}