import type { AbilityKey, AbilityScores } from '@/lib/rules';

const ABILITIES: AbilityKey[] = ['str', 'dex', 'con', 'int', 'wis', 'cha'];

const ABILITY_BY_WORD: Record<string, AbilityKey> = {
  strength: 'str', dexterity: 'dex', constitution: 'con',
  intelligence: 'int', wisdom: 'wis', charisma: 'cha',
};

/**
 * Parse a 5e race's ASI prose into structured ability bonuses. Handles the Human
 * "Your ability scores each increase by 1" case and the usual "Your X score
 * increases by N[, and your Y score increases by M]" form.
 */
export function parseAsiBonuses(asi: string): Partial<AbilityScores> {
  const out: Partial<AbilityScores> = {};
  const each = /ability scores?\s+each\s+increase(?:s)?\s+by\s+(\d+)/i.exec(asi);
  if (each) {
    const n = Number(each[1]);
    for (const a of ABILITIES) out[a] = (out[a] ?? 0) + n;
    return out;
  }
  for (const m of asi.matchAll(/(strength|dexterity|constitution|intelligence|wisdom|charisma)\s+score\s+(?:each\s+)?increase(?:s)?\s+by\s+(\d+)/gi)) {
    const key = ABILITY_BY_WORD[m[1]!.toLowerCase()];
    if (key) out[key] = (out[key] ?? 0) + Number(m[2]);
  }
  return out;
}

/** A "skill label/key → key" resolver for the active system. */
export function makeSkillResolver(skills: readonly { key: string; label: string }[]): (name: string) => string | undefined {
  const byLabel = new Map<string, string>();
  for (const s of skills) { byLabel.set(s.label.toLowerCase(), s.key); byLabel.set(s.key.toLowerCase(), s.key); }
  return (name) => byLabel.get(name.trim().toLowerCase());
}

/** Fixed skill proficiencies a 5e background grants (ignores "either/or/choice" clauses). */
export function parseBackgroundSkills(skills: string, resolve: (n: string) => string | undefined): string[] {
  const out: string[] = [];
  for (let token of skills.split(',')) {
    token = token.replace(/\b(and|plus)\b/gi, '').replace(/\.$/, '').trim();
    if (!token) continue;
    if (/either|\bor\b|choice|between/i.test(token)) break; // a choose-one clause — stop here
    const key = resolve(token);
    if (key && !out.includes(key)) out.push(key);
  }
  return out;
}

/** Skill proficiencies granted by racial traits ("proficiency in the X skill"). */
export function parseTraitSkills(traits: string, resolve: (n: string) => string | undefined): string[] {
  const out: string[] = [];
  for (const m of traits.matchAll(/proficiency in the ([A-Za-z][A-Za-z ]*?) skill/gi)) {
    const key = resolve(m[1]!);
    if (key && !out.includes(key)) out.push(key);
  }
  return out;
}
