import type { ClassDef } from '../progression';

/**
 * Curated PF2e class data for the guided builder. There is no class data file on
 * disk, so the core classes' HP, key ability, initial proficiencies, trained-skill
 * count, and caster type are authored here. `hitDie` holds HP-per-level (PF2e style).
 * Save ranks are keyed by the ability the save uses (con/dex/wis) to match the sheet.
 */
export const PF2E_CLASSES: ClassDef[] = [
  cls('Alchemist', 8, ['int'], { con: 'expert', dex: 'expert', wis: 'trained' }, 'trained', 3, 'none'),
  cls('Barbarian', 12, ['str'], { con: 'expert', dex: 'trained', wis: 'expert' }, 'expert', 3, 'none'),
  cls('Bard', 8, ['cha'], { con: 'trained', dex: 'trained', wis: 'expert' }, 'expert', 4, 'full', 'cha'),
  cls('Champion', 10, ['str'], { con: 'expert', dex: 'trained', wis: 'expert' }, 'trained', 2, 'none'),
  cls('Cleric', 8, ['wis'], { con: 'trained', dex: 'trained', wis: 'expert' }, 'trained', 2, 'full', 'wis'),
  cls('Druid', 8, ['wis'], { con: 'trained', dex: 'expert', wis: 'expert' }, 'trained', 2, 'full', 'wis'),
  cls('Fighter', 10, ['str', 'dex'], { con: 'expert', dex: 'expert', wis: 'trained' }, 'expert', 3, 'none'),
  cls('Investigator', 8, ['int'], { con: 'trained', dex: 'expert', wis: 'expert' }, 'expert', 4, 'none'),
  cls('Monk', 10, ['str', 'dex'], { con: 'expert', dex: 'expert', wis: 'expert' }, 'trained', 4, 'none'),
  cls('Oracle', 8, ['cha'], { con: 'trained', dex: 'trained', wis: 'expert' }, 'trained', 3, 'full', 'cha'),
  cls('Ranger', 10, ['str', 'dex'], { con: 'expert', dex: 'expert', wis: 'trained' }, 'expert', 4, 'none'),
  cls('Rogue', 8, ['dex'], { con: 'trained', dex: 'expert', wis: 'expert' }, 'expert', 7, 'none'),
  cls('Sorcerer', 6, ['cha'], { con: 'trained', dex: 'trained', wis: 'expert' }, 'trained', 2, 'full', 'cha'),
  cls('Swashbuckler', 10, ['dex'], { con: 'trained', dex: 'expert', wis: 'expert' }, 'expert', 4, 'none'),
  cls('Witch', 6, ['int'], { con: 'trained', dex: 'trained', wis: 'expert' }, 'trained', 3, 'full', 'int'),
  cls('Wizard', 6, ['int'], { con: 'trained', dex: 'trained', wis: 'expert' }, 'trained', 2, 'full', 'int'),
];

function cls(
  name: string, hp: number, keyAbilities: ClassDef['keyAbilities'],
  saves: NonNullable<ClassDef['saveRanks']>, perception: ClassDef['perception'],
  skillCount: number, caster: ClassDef['caster'], spellAbility?: ClassDef['spellAbility'],
): ClassDef {
  return {
    name, hitDie: hp, keyAbilities, saveProficient: [], saveRanks: saves,
    perception: perception ?? 'trained', skillKeys: [], skillCount, caster,
    ...(spellAbility ? { spellAbility, spellRank: 'trained' as const } : {}),
  };
}

/** PF2e HP = ancestry HP + (class HP + CON mod) × level. */
export function pf2eHp(classHp: number, level: number, conMod: number, ancestryHp: number): number {
  const lvl = Math.max(1, Math.min(20, Math.floor(level) || 1));
  return Math.max(1, ancestryHp + (classHp + conMod) * lvl);
}

/**
 * Spell slots per rank for a full caster. A new rank unlocks at each odd level;
 * each available rank gets 3 slots (the standard for prepared/spontaneous casters).
 * Approximate and editable on the sheet.
 */
export function pf2eSlots(caster: ClassDef['caster'], level: number): { level: number; max: number; current: number }[] {
  if (caster !== 'full') return [];
  const lvl = Math.max(1, Math.min(20, Math.floor(level) || 1));
  const topRank = Math.min(10, Math.ceil(lvl / 2));
  const slots: { level: number; max: number; current: number }[] = [];
  for (let r = 1; r <= topRank; r++) {
    const max = r === 10 ? 1 : 3;
    slots.push({ level: r, max, current: max });
  }
  return slots;
}

/** Levels granting 4 ability boosts. */
export function pf2eBoostLevels(): number[] {
  return [5, 10, 15, 20];
}

/** Levels granting a skill increase. */
export function pf2eSkillIncreaseLevels(): number[] {
  return [3, 5, 7, 9, 11, 13, 15, 17, 19];
}
