// ─── Discipline Card Utility Functions ─────────────────────────────────────────
// Shared helpers for computing perk effects and stat bonus totals in the UI.

import type { DisciplinePerk } from '@/lib/game/types/disciplines';
import { calculatePerkTier } from '@/lib/game/utils/discipline-math';
import { TICK_MS } from '@/lib/game/constants/core';

// TICK_MS = 200, so 5 ticks per second
export const TICKS_PER_SECOND = 1000 / TICK_MS;

// Stat keys that represent per-second rates. All other stat keys are
// flat bonuses (capacities, powers, multipliers, percentages, etc.).
const RATE_STAT_KEYS = new Set([
  'regenBonus',
  'disciplineXpBonus',
]);

// Dynamic stat keys that are rates (checked by prefix)
const RATE_STAT_PREFIXES = [
  'conversion_',
];

export function isRateStat(statKey: string): boolean {
  if (RATE_STAT_KEYS.has(statKey)) return true;
  return RATE_STAT_PREFIXES.some((prefix) => statKey.startsWith(prefix));
}

export interface ComputedPerkEffect {
  description: string;
  currentEffect: string;
}

/**
 * Compute the current effect for a perk based on XP.
 * Returns a human-readable string like "+5.25/sec" or "+50 (unlocked)".
 */
export function computePerkCurrentEffect(
  perk: DisciplinePerk,
  xp: number,
): string {
  if (xp < perk.threshold) {
    return `at ${perk.threshold} XP`;
  }

  if (!perk.bonus) {
    return 'unlocked';
  }

  const { amount, stat } = perk.bonus;
  const rateSuffix = isRateStat(stat) ? '/sec' : '';

  switch (perk.type) {
    case 'once':
      return `+${amount}${rateSuffix}`;
    case 'infinite': {
      const tier = calculatePerkTier(xp, perk.threshold, perk.value);
      const total = tier * amount;
      if (total === 0) return `+0${rateSuffix}`;
      return `+${total.toFixed(2)}${rateSuffix}`;
    }
    case 'capped': {
      let tier = calculatePerkTier(xp, perk.threshold, perk.value);
      if (perk.maxTier !== undefined) {
        tier = Math.min(tier, perk.maxTier);
      }
      const total = tier * amount;
      if (total === 0) return `+0${rateSuffix}`;
      return `+${total.toFixed(2)}${rateSuffix}`;
    }
    default:
      return 'active';
  }
}

/**
 * Compute total perk bonus amount for a specific statKey from all unlocked perks.
 * Mirrors the logic in computeDisciplineEffects() for 'once', 'infinite', and 'capped' perks.
 */
export function computeTotalPerkBonusForStat(
  perks: DisciplinePerk[],
  xp: number,
  statKey: string,
): number {
  let total = 0;
  for (const perk of perks) {
    if (xp < perk.threshold) continue;
    if (!perk.bonus || perk.bonus.stat !== statKey) continue;

    switch (perk.type) {
      case 'once':
        total += perk.bonus.amount;
        break;
      case 'infinite': {
        const tier = calculatePerkTier(xp, perk.threshold, perk.value);
        if (tier > 0) total += tier * perk.bonus.amount;
        break;
      }
      case 'capped': {
        let tier = calculatePerkTier(xp, perk.threshold, perk.value);
        if (tier > 0 && perk.maxTier !== undefined) {
          tier = Math.min(tier, perk.maxTier);
        }
        if (tier > 0) total += tier * perk.bonus.amount;
        break;
      }
    }
  }
  return total;
}
