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 }));
}

/**
 * PHB multiclass spellcaster level: full-caster levels count fully, half-casters
 * halve (floored), third-casters third (floored). Warlock pact magic is separate
 * and excluded. The combined level reads the standard full-caster slot table —
 * so e.g. Paladin 6 / Sorcerer 1 = level (3 + 1) = 4 → 4/3 first-/second slots.
 */
export function multiclassCasterLevel(parts: { full?: number; half?: number; third?: number }): number {
  return (parts.full ?? 0) + Math.floor((parts.half ?? 0) / 2) + Math.floor((parts.third ?? 0) / 3);
}
export function multiclassSlots(parts: { full?: number; half?: number; third?: number }): { level: number; max: number; current: number }[] {
  const lvl = multiclassCasterLevel(parts);
  if (lvl < 1) return []; // a single half-caster level (e.g. Paladin 1) grants no slots
  const table = FULL[Math.min(20, lvl)];
  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;
}

/**
 * Curated official 5e subclasses, merged into the builder's class list on top of
 * whatever the on-disk classes.json carries (which is SRD + third-party homebrew and
 * is missing most PHB/XGE archetypes). Keyed by class name; deduped by name at merge
 * time. Descriptions are short "what it plays like" blurbs — subclass *features* are
 * not yet auto-applied (a separate task), so these add the missing options to pick.
 */
export const DND5E_SUBCLASSES: Record<string, { name: string; desc: string }[]> = {
  Barbarian: [
    { name: 'Path of the Totem Warrior', desc: 'Adopt a spirit animal (Bear/Eagle/Wolf) for resilience, mobility, or pack tactics.' },
    { name: 'Path of the Ancestral Guardian', desc: 'Spectral ancestors shield your allies and punish foes who ignore you.' },
    { name: 'Path of the Storm Herald', desc: 'Your rage radiates an aura of desert heat, sea cold, or tundra lightning.' },
    { name: 'Path of the Zealot', desc: 'A divine warrior whose rage deals extra radiant/necrotic damage and cheats death.' },
    { name: 'Path of the Beast', desc: 'Grow natural weapons — bite, claws, or tail — that change each rage.' },
    { name: 'Path of Wild Magic', desc: 'Rage triggers chaotic magical surges and bends luck for your allies.' },
    { name: 'Path of the Battlerager', desc: 'A spiked-armor dwarf who rages into the enemy and damages whatever grapples it.' },
  ],
  Bard: [
    { name: 'College of Valor', desc: 'A martial skald: armor, extra attack, and Combat Inspiration for allies.' },
    { name: 'College of Glamour', desc: 'Fey-charming performer who beguiles foes and rallies allies with temp HP.' },
    { name: 'College of Swords', desc: 'A blade-flourishing duelist who weaves Bardic Inspiration into weapon attacks.' },
    { name: 'College of Whispers', desc: 'A sinister spy who plants fear and wears the identity of those it kills.' },
    { name: 'College of Eloquence', desc: 'A peerless orator — unfailing Persuasion and inspiration that never wastes.' },
    { name: 'College of Creation', desc: 'Sings reality into being: animate objects and a Mote of Potential.' },
    { name: 'College of Spirits', desc: 'Channels tales of the dead through a Spiritual Focus for random boons.' },
  ],
  Cleric: [
    { name: 'Knowledge Domain', desc: 'A scholar-priest with bonus skills, languages, and read-the-past magic.' },
    { name: 'Light Domain', desc: 'Radiant blaster with Warding Flare and a fiery turn-undead burst.' },
    { name: 'Nature Domain', desc: 'A druidic cleric with heavy armor, a skill, and charm of beasts/plants.' },
    { name: 'Tempest Domain', desc: 'Storm-caller: maximize lightning/thunder and smite attackers with thunderbolts.' },
    { name: 'Trickery Domain', desc: 'A deceiver who blesses allies with poison and conjures duplicate images.' },
    { name: 'War Domain', desc: 'A frontline crusader with bonus weapon attacks and divine guidance to hit.' },
    { name: 'Death Domain', desc: 'A necromantic cleric wielding extra necrotic damage and reaper cantrips.' },
    { name: 'Arcana Domain', desc: 'A mage-priest who adds wizard spells and disrupts other magic.' },
    { name: 'Forge Domain', desc: 'An armored smith who blesses armor/weapons and channels fire.' },
    { name: 'Grave Domain', desc: 'A warden of death’s border who heals the dying and curses the marked.' },
    { name: 'Order Domain', desc: 'A lawful enforcer granting allies free attacks when you heal or charm.' },
    { name: 'Peace Domain', desc: 'A bonded protector who links allies to share defenses and reactions.' },
    { name: 'Twilight Domain', desc: 'A guardian of the night granting darkvision and rolling temp-HP aura.' },
  ],
  Druid: [
    { name: 'Circle of the Moon', desc: 'A combat shapeshifter who wild-shapes into powerful beasts as a bonus action.' },
    { name: 'Circle of Dreams', desc: 'A fey-touched healer with a restful Hearth and Balm of the Summer Court.' },
    { name: 'Circle of the Shepherd', desc: 'A summoner who plants totem spirits that buff and heal conjured allies.' },
    { name: 'Circle of Spores', desc: 'A necro-druid wreathed in halo of spores that deal damage and raise the dead.' },
    { name: 'Circle of Stars', desc: 'An astral druid adopting Archer/Chalice/Dragon Starry Forms.' },
    { name: 'Circle of Wildfire', desc: 'Bonded to a wildfire spirit of flame and renewal — burn and heal.' },
  ],
  Fighter: [
    { name: 'Battle Master', desc: 'A tactician with superiority dice and maneuvers (trip, disarm, riposte…).' },
    { name: 'Eldritch Knight', desc: 'A martial caster blending wizard spells with weapon attacks.' },
    { name: 'Arcane Archer', desc: 'An elf marksman with magical Arcane Shots (banishing, seeking, grasping).' },
    { name: 'Cavalier', desc: 'A mounted/guardian fighter who marks foes and protects allies.' },
    { name: 'Samurai', desc: 'A resolute duelist whose Fighting Spirit grants advantage and temp HP.' },
    { name: 'Psi Warrior', desc: 'A psionic soldier using Psionic Energy dice to shove, shield, and strike.' },
    { name: 'Rune Knight', desc: 'A giant-runed warrior who grows large and carves magical runes into gear.' },
    { name: 'Echo Knight', desc: 'Summons a manifest echo of itself to attack and teleport from.' },
    { name: 'Banneret (Purple Dragon Knight)', desc: 'An inspiring leader who rallies and protects the whole party.' },
  ],
  Monk: [
    { name: 'Way of Shadow', desc: 'A ninja who melds into darkness and teleports between shadows.' },
    { name: 'Way of the Four Elements', desc: 'A martial elementalist who spends ki to cast elemental disciplines.' },
    { name: 'Way of the Drunken Master', desc: 'An unpredictable brawler who weaves, redirects misses, and disengages freely.' },
    { name: 'Way of the Kensei', desc: 'A weapon-bonded monk who makes chosen weapons into monk weapons.' },
    { name: 'Way of the Sun Soul', desc: 'Hurls radiant ki bolts and unleashes a searing burst.' },
    { name: 'Way of Mercy', desc: 'A masked medic who heals with one hand and inflicts necrotic harm with the other.' },
    { name: 'Way of the Astral Self', desc: 'Manifests spectral arms and body powered by Wisdom.' },
  ],
  Paladin: [
    { name: 'Oath of the Ancients', desc: 'A fey-light champion of joy with retributive aura and nature magic.' },
    { name: 'Oath of Vengeance', desc: 'A relentless avenger who marks a foe and hunts it down.' },
    { name: 'Oath of Conquest', desc: 'A tyrant of fear whose aura freezes the frightened in place.' },
    { name: 'Oath of Redemption', desc: 'A pacifist peacemaker who rebukes attackers and shields allies.' },
    { name: 'Oath of Glory', desc: 'A heroic athlete who boosts allies’ speed and damage to inspire legend.' },
    { name: 'Oath of the Watchers', desc: 'A sentinel against extraplanar threats with bonus initiative and saves.' },
    { name: 'Oath of the Crown', desc: 'A sworn protector of civilization who taunts and intercepts blows.' },
    { name: 'Oathbreaker', desc: 'A fallen paladin who commands undead and aura-boosts cruelty.' },
  ],
  Ranger: [
    { name: 'Beast Master', desc: 'Bonds with an animal companion that fights at your command.' },
    { name: 'Gloom Stalker', desc: 'An ambusher of the dark — extra first-round attack, invisible in shadow.' },
    { name: 'Horizon Walker', desc: 'A planar sentinel dealing force damage and teleporting between attacks.' },
    { name: 'Monster Slayer', desc: 'Studies a foe to exploit its weakness and turn its own attacks back.' },
    { name: 'Fey Wanderer', desc: 'A whimsical wanderer adding psychic damage and charm to its hunt.' },
    { name: 'Swarmkeeper', desc: 'Accompanied by a magical swarm that moves, damages, and protects.' },
    { name: 'Drakewarden', desc: 'Raises a draconic companion that grows into a rideable mount.' },
  ],
  Rogue: [
    { name: 'Mastermind', desc: 'A master of intrigue and tactics: extra tool/language proficiencies, Help as a bonus action at range, and uncanny insight into a creature’s drives.' },
    { name: 'Assassin', desc: 'A killer who excels at ambush — auto-crits on surprised foes and disguises.' },
    { name: 'Arcane Trickster', desc: 'A spell-thief blending illusion/enchantment magic with mage-hand legerdemain.' },
    { name: 'Scout', desc: 'A skirmisher and survivalist who darts away when foes close in.' },
    { name: 'Swashbuckler', desc: 'A dashing duelist who sneak-attacks one-on-one and disengages with flair.' },
    { name: 'Inquisitive', desc: 'A sleuth who reads tells, finds weak points, and sees through deception.' },
    { name: 'Phantom', desc: 'A death-touched rogue who steals skills from the slain and deals soul damage.' },
    { name: 'Soulknife', desc: 'A psionic assassin who manifests psychic blades and walks unseen.' },
  ],
  Sorcerer: [
    { name: 'Wild Magic', desc: 'Chaotic surges and Tides of Chaos — power at the cost of unpredictability.' },
    { name: 'Divine Soul', desc: 'Heaven-touched caster with access to cleric spells and favored rerolls.' },
    { name: 'Shadow Magic', desc: 'A Shadowfell-born caster with a hound of ill omen and a brush with death.' },
    { name: 'Storm Sorcery', desc: 'Rides the wind — fly on a casting, blast lightning/thunder.' },
    { name: 'Aberrant Mind', desc: 'A psionic mind with telepathy and subtle, Sorcery-Point-fueled spells.' },
    { name: 'Clockwork Soul', desc: 'Channels cosmic order to negate advantage/disadvantage and ward allies.' },
  ],
  Warlock: [
    { name: 'The Archfey', desc: 'A fey patron granting fae presence, misty escape, and beguiling defenses.' },
    { name: 'The Great Old One', desc: 'An alien patron of telepathy, psychic crits, and mind-enslaving magic.' },
    { name: 'The Celestial', desc: 'A radiant patron granting healing light and resurrection of allies.' },
    { name: 'The Hexblade', desc: 'A weapon-bonded patron — Charisma attacks, a curse, and armor proficiency.' },
    { name: 'The Fathomless', desc: 'A deep-sea patron with a tentacle of the depths and abyssal mobility.' },
    { name: 'The Genie', desc: 'A noble genie patron granting a bottle refuge and elemental damage.' },
    { name: 'The Undead', desc: 'A deathless patron of dread — frighten foes and ignore being downed.' },
    { name: 'The Undying', desc: 'A patron of unlife granting resilience against death and disease.' },
  ],
  Wizard: [
    { name: 'School of Abjuration', desc: 'A protective ward absorbs damage; counter and dispel magic better.' },
    { name: 'School of Conjuration', desc: 'A summoner who conjures objects and minor creatures and teleports.' },
    { name: 'School of Divination', desc: 'A seer who replaces rolls with foreseen Portent dice.' },
    { name: 'School of Enchantment', desc: 'A charmer who hypnotizes and redirects attacks onto other foes.' },
    { name: 'School of Illusion', desc: 'A trickster whose illusions become partly real and reshape on the fly.' },
    { name: 'School of Necromancy', desc: 'A death-mage who commands the undead and drains life to heal.' },
    { name: 'School of Transmutation', desc: 'A shapechanger with a transmuter’s stone of versatile boons.' },
    { name: 'Bladesinging', desc: 'An elven sword-mage who weaves dazzling defense with melee and spells.' },
    { name: 'War Magic', desc: 'A battle-mage balancing arcane deflection with offensive surges.' },
    { name: 'Order of Scribes', desc: 'A living spellbook that swaps damage types and pens spells cheaply.' },
    { name: 'Chronurgy Magic', desc: 'A time-mage who alters initiative and saving throws with temporal magic.' },
    { name: 'Graviturgy Magic', desc: 'A gravity-mage who manipulates weight, speed, and crushing force.' },
  ],
};
