/**
 * Pure function — given the level-up parameters, returns the ordered list of
 * wizard step kinds the player must walk through (D-10 step ordering).
 *
 * No NestJS, no Prisma, no I/O. Output is fully determined by inputs.
 */
import type { StepKind } from './types';

export interface ComputeStepsInput {
  targetLevel: number;
  className: string;
  hasFreeArchetype: boolean;
  isCaster: boolean;
  isSpontaneousCaster: boolean;
  classProgressionHasChoiceType: boolean;
}

/** PF2e ability-boost levels (every 5th level after 5). */
const BOOST_LEVELS: ReadonlySet<number> = new Set([5, 10, 15, 20]);

/** PF2e skill-increase steps (level 3 and every 2 levels thereafter). */
const SKILL_INCREASE_LEVELS: ReadonlySet<number> = new Set([3, 5, 7, 9, 11, 13, 15, 17, 19]);

/** General-feat slot levels (PF2e CRB). */
const GENERAL_FEAT_LEVELS: ReadonlySet<number> = new Set([3, 7, 11, 15, 19]);

/**
 * Ancestry-feat slot levels (PF2e CRB) — character creation grants level 1, but
 * this function is for level-ups (1 is excluded by callers / handled below).
 */
const ANCESTRY_FEAT_LEVELS: ReadonlySet<number> = new Set([1, 5, 9, 13, 17]);

/**
 * Returns the ordered list of wizard step kinds for a level-up.
 * Step ordering follows D-10:
 *   class-features → class-feature-choice (if any)
 *   → boost (if level ∈ {5,10,15,20})
 *   → skill-increase (if level ∈ {3,5,7,...,19})
 *   → feat-class (if even level)
 *   → feat-skill (if even level)
 *   → feat-general (if level ∈ {3,7,11,15,19})
 *   → feat-ancestry (if level ∈ {5,9,13,17}; excludes L1)
 *   → feat-archetype (if hasFreeArchetype)
 *   → spellcaster (if isCaster)
 *   → review
 */
export function computeApplicableSteps(input: ComputeStepsInput): StepKind[] {
  const { targetLevel, hasFreeArchetype, isCaster, classProgressionHasChoiceType } = input;
  const steps: StepKind[] = ['class-features'];

  if (classProgressionHasChoiceType) steps.push('class-feature-choice');
  if (BOOST_LEVELS.has(targetLevel)) steps.push('boost');
  if (SKILL_INCREASE_LEVELS.has(targetLevel)) steps.push('skill-increase');
  if (targetLevel % 2 === 0) {
    steps.push('feat-class');
    steps.push('feat-skill');
  }
  if (GENERAL_FEAT_LEVELS.has(targetLevel)) steps.push('feat-general');
  if (ANCESTRY_FEAT_LEVELS.has(targetLevel) && targetLevel !== 1) {
    steps.push('feat-ancestry');
  }
  if (hasFreeArchetype) steps.push('feat-archetype');
  if (isCaster) steps.push('spellcaster');

  steps.push('review');
  return steps;
}
