import type { EncounterDefinition } from '@fog-explorer/api-interfaces';
import { ALLY_FIRST_NAMES } from './survivors';
import { KILLER_NAMES } from './killers';
import encountersData from './encounters.json';

interface RawEncounter {
  key: string;
  baseProbability: number;
  tags: string[];
  tier: number;
  flavorSuccess: string[];
  flavorFailure: string[];
}
interface EncountersFile {
  version: string;
  encounters: RawEncounter[];
}

export interface LibraryEncounter extends EncounterDefinition {
  tier: 1 | 2 | 3;
  flavorSuccess: string[];
  flavorFailure: string[];
}

export interface FlavorContext {
  success: boolean;
  killerName?: string;
}

const LIBRARY_VERSION: string = encountersData.version;

const ALL_ENCOUNTERS: LibraryEncounter[] = encountersData.encounters.map((e) => ({
  key: e.key,
  baseProbability: e.baseProbability,
  tags: e.tags,
  tier: e.tier as 1 | 2 | 3,
  flavorSuccess: e.flavorSuccess,
  flavorFailure: e.flavorFailure,
}));

export function getLibraryVersion(): string {
  return LIBRARY_VERSION;
}

export function getEncounterById(key: string): LibraryEncounter | undefined {
  return ALL_ENCOUNTERS.find((e) => e.key === key);
}

export function getEncountersByTier(tier: 1 | 2 | 3): LibraryEncounter[] {
  return ALL_ENCOUNTERS.filter((e) => e.tier === tier);
}

export function getRandomEncounterByTier(
  tier: 1 | 2 | 3,
  rng: () => number
): LibraryEncounter {
  const pool = getEncountersByTier(tier);
  if (pool.length === 0) {
    throw new Error(`No encounters for tier ${tier}`);
  }
  return pool[Math.floor(rng() * pool.length)];
}

export function pickFlavor(
  encounter: LibraryEncounter,
  ctx: FlavorContext,
  rng: () => number
): string {
  const pool = ctx.success ? encounter.flavorSuccess : encounter.flavorFailure;
  const raw = pool[Math.floor(rng() * pool.length)];
  return expandTokens(raw, ctx, rng);
}

function expandTokens(text: string, ctx: FlavorContext, rng: () => number): string {
  let out = text.replace(/\{\{ally\}\}/g, () => {
    return ALLY_FIRST_NAMES[Math.floor(rng() * ALLY_FIRST_NAMES.length)];
  });
  out = out.replace(/\{\{killer\}\}/g, () => {
    return ctx.killerName ?? KILLER_NAMES[Math.floor(rng() * KILLER_NAMES.length)];
  });
  return out;
}
