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

/**
 * Curated 5e SRD class data for the guided builder. The on-disk MPMB files carry
 * only names, so hit dice / proficiencies / caster type are authored here for the
 * core classes. Unknown classes fall back to manual entry in the wizard.
 */
export const DND5E_CLASSES: ClassDef[] = [
  { name: 'Barbarian', hitDie: 12, keyAbilities: ['str'], saveProficient: ['str', 'con'], skillCount: 2,
    skillKeys: ['animal-handling', 'athletics', 'intimidation', 'nature', 'perception', 'survival'], caster: 'none' },
  { name: 'Bard', hitDie: 8, keyAbilities: ['cha'], saveProficient: ['dex', 'cha'], skillCount: 3,
    skillKeys: [], caster: 'full', spellAbility: 'cha' },
  { name: 'Cleric', hitDie: 8, keyAbilities: ['wis'], saveProficient: ['wis', 'cha'], skillCount: 2,
    skillKeys: ['history', 'insight', 'medicine', 'persuasion', 'religion'], caster: 'full', spellAbility: 'wis' },
  { name: 'Druid', hitDie: 8, keyAbilities: ['wis'], saveProficient: ['int', 'wis'], skillCount: 2,
    skillKeys: ['arcana', 'animal-handling', 'insight', 'medicine', 'nature', 'perception', 'religion', 'survival'], caster: 'full', spellAbility: 'wis' },
  { name: 'Fighter', hitDie: 10, keyAbilities: ['str', 'dex'], saveProficient: ['str', 'con'], skillCount: 2,
    skillKeys: ['acrobatics', 'animal-handling', 'athletics', 'history', 'insight', 'intimidation', 'perception', 'survival'], caster: 'none' },
  { name: 'Monk', hitDie: 8, keyAbilities: ['dex', 'wis'], saveProficient: ['str', 'dex'], skillCount: 2,
    skillKeys: ['acrobatics', 'athletics', 'history', 'insight', 'religion', 'stealth'], caster: 'none' },
  { name: 'Paladin', hitDie: 10, keyAbilities: ['str', 'cha'], saveProficient: ['wis', 'cha'], skillCount: 2,
    skillKeys: ['athletics', 'insight', 'intimidation', 'medicine', 'persuasion', 'religion'], caster: 'half', spellAbility: 'cha' },
  { name: 'Ranger', hitDie: 10, keyAbilities: ['dex', 'wis'], saveProficient: ['str', 'dex'], skillCount: 3,
    skillKeys: ['animal-handling', 'athletics', 'insight', 'investigation', 'nature', 'perception', 'stealth', 'survival'], caster: 'half', spellAbility: 'wis' },
  { name: 'Rogue', hitDie: 8, keyAbilities: ['dex'], saveProficient: ['dex', 'int'], skillCount: 4,
    skillKeys: ['acrobatics', 'athletics', 'deception', 'insight', 'intimidation', 'investigation', 'perception', 'performance', 'persuasion', 'sleight-of-hand', 'stealth'], caster: 'none' },
  { name: 'Sorcerer', hitDie: 6, keyAbilities: ['cha'], saveProficient: ['con', 'cha'], skillCount: 2,
    skillKeys: ['arcana', 'deception', 'insight', 'intimidation', 'persuasion', 'religion'], caster: 'full', spellAbility: 'cha' },
  { name: 'Warlock', hitDie: 8, keyAbilities: ['cha'], saveProficient: ['wis', 'cha'], skillCount: 2,
    skillKeys: ['arcana', 'deception', 'history', 'intimidation', 'investigation', 'nature', 'religion'], caster: 'pact', spellAbility: 'cha' },
  { name: 'Wizard', hitDie: 6, keyAbilities: ['int'], saveProficient: ['int', 'wis'], skillCount: 2,
    skillKeys: ['arcana', 'history', 'insight', 'investigation', 'medicine', 'religion'], caster: 'full', spellAbility: 'int' },
];

// Spell slots [1st..9th] by character level for a full caster (PHB).
const FULL: Record<number, number[]> = {
  1: [2], 2: [3], 3: [4, 2], 4: [4, 3], 5: [4, 3, 2], 6: [4, 3, 3], 7: [4, 3, 3, 1], 8: [4, 3, 3, 2],
  9: [4, 3, 3, 3, 1], 10: [4, 3, 3, 3, 2], 11: [4, 3, 3, 3, 2, 1], 12: [4, 3, 3, 3, 2, 1],
  13: [4, 3, 3, 3, 2, 1, 1], 14: [4, 3, 3, 3, 2, 1, 1], 15: [4, 3, 3, 3, 2, 1, 1, 1], 16: [4, 3, 3, 3, 2, 1, 1, 1],
  17: [4, 3, 3, 3, 2, 1, 1, 1, 1], 18: [4, 3, 3, 3, 3, 1, 1, 1, 1], 19: [4, 3, 3, 3, 3, 2, 1, 1, 1], 20: [4, 3, 3, 3, 3, 2, 2, 1, 1],
};
// Half caster (Paladin/Ranger), spells from level 2.
const HALF: Record<number, number[]> = {
  2: [2], 3: [3], 4: [3], 5: [4, 2], 6: [4, 2], 7: [4, 3], 8: [4, 3], 9: [4, 3, 2], 10: [4, 3, 2],
  11: [4, 3, 3], 12: [4, 3, 3], 13: [4, 3, 3, 1], 14: [4, 3, 3, 1], 15: [4, 3, 3, 2], 16: [4, 3, 3, 2],
  17: [4, 3, 3, 3, 1], 18: [4, 3, 3, 3, 1], 19: [4, 3, 3, 3, 2], 20: [4, 3, 3, 3, 2],
};
// Warlock pact magic: [slotCount, slotLevel].
const PACT: Record<number, [number, number]> = {
  1: [1, 1], 2: [2, 1], 3: [2, 2], 4: [2, 2], 5: [2, 3], 6: [2, 3], 7: [2, 4], 8: [2, 4], 9: [2, 5], 10: [2, 5],
  11: [3, 5], 12: [3, 5], 13: [3, 5], 14: [3, 5], 15: [3, 5], 16: [3, 5], 17: [4, 5], 18: [4, 5], 19: [4, 5], 20: [4, 5],
};

function clamp(level: number): number {
  return Math.max(1, Math.min(20, Math.floor(level) || 1));
}

export function dnd5eSlots(caster: ClassDef['caster'], level: number): { level: number; max: number; current: number }[] {
  const lvl = clamp(level);
  const table = caster === 'full' ? FULL[lvl] : caster === 'half' ? HALF[lvl] : undefined;
  if (!table) return [];
  return table.map((max, i) => ({ level: i + 1, max, current: max }));
}

export function dnd5ePact(level: number): { level: number; max: number; current: number } | undefined {
  const p = PACT[clamp(level)];
  return p ? { level: p[1], max: p[0], current: p[0] } : undefined;
}

/** Average HP at a level: max die at L1, then per-level average + CON each level. */
export function dnd5eHp(hitDie: number, level: number, conMod: number): number {
  const lvl = clamp(level);
  const avg = Math.ceil(hitDie / 2) + 1;
  return Math.max(1, hitDie + conMod + (lvl - 1) * (avg + conMod));
}

/** Levels that grant an Ability Score Improvement (or feat). Includes class extras. */
export function dnd5eAsiLevels(className: string): number[] {
  const base = [4, 8, 12, 16, 19];
  const c = className.toLowerCase();
  if (c === 'fighter') return [...base, 6, 14].sort((a, b) => a - b);
  if (c === 'rogue') return [...base, 10].sort((a, b) => a - b);
  return base;
}
