import type { BossGroupCollection, GameModeId, GameSettings, HunterSave, SaveSlotId } from "./types";
import { AVAILABLE_BOSS_IDS, BOSS_DEFINITIONS, BOSS_GROUPS } from "../game/bossCatalog";
import { createClassInventory } from "../game/healers";
import type { BossId } from "../game/types";
import { createDefaultGearProgress } from "../game/progression/gear";
import { BOSS_PET_DROPS, GROUP_DROP_TABLES, createEmptyCollectionLog, type CollectionLog, type LootRarity, type MaterialStack } from "../game/progression/loot";

export const DEFAULT_SETTINGS: GameSettings = {
  masterVolume: 80,
  reducedMotion: false,
  damageNumbers: true,
  largeText: false,
};

const RARITY_LABELS: Record<LootRarity, BossGroupCollection["drops"][number]["rarity"]> = {
  common: "Common",
  uncommon: "Uncommon",
  rare: "Rare",
  epic: "Epic",
  legendary: "Legendary",
};

export function buildCollections(collectionLog: CollectionLog, bossKills: Record<string, number>): BossGroupCollection[] {
  return BOSS_GROUPS.map((group) => {
    const table = GROUP_DROP_TABLES[group.id];
    const bosses = group.bossIds.map((bossId) => {
      const pet = BOSS_PET_DROPS[bossId];
      return {
        bossId,
        bossName: BOSS_DEFINITIONS[bossId].name,
        kills: bossKills[bossId] ?? 0,
        pet: {
          id: pet.id,
          name: pet.name,
          icon: pet.glyph,
          rarity: RARITY_LABELS[pet.rarity],
          count: collectionLog.petsFound[pet.id] ?? 0,
          chance: pet.chanceLabel,
          kind: pet.kind,
        },
      };
    });
    return {
      groupId: group.id,
      groupLetter: group.letter,
      groupName: group.name,
      coreMechanic: group.coreMechanic,
      defeated: bosses.some((boss) => boss.kills > 0),
      drops: table.entries.map((drop) => ({
        id: drop.id,
        name: drop.name,
        icon: drop.glyph,
        rarity: RARITY_LABELS[drop.rarity],
        count: collectionLog.dropsFound[drop.id] ?? 0,
        chance: drop.chanceLabel,
        itemLevel: drop.itemLevel,
        kind: drop.kind,
      })),
      bosses,
    };
  });
}

export const DEFAULT_COLLECTION_LOG: CollectionLog = createEmptyCollectionLog();
export const DEFAULT_COLLECTIONS: BossGroupCollection[] = buildCollections(DEFAULT_COLLECTION_LOG, {});

export const MODE_COPY: Record<GameModeId, { eyebrow: string; title: string; description: string; detail: string; status: string }> = {
  "roguelike-pve": {
    eyebrow: "1–4 hunters · randomized PVE",
    title: "PVE",
    description: "Enter without an encounter briefing, adapt to two randomized guardians, and build toward a full roguelike run.",
    detail: "Two bosses selected when the run begins",
    status: "Playable now",
  },
  "rogue-trials": {
    eyebrow: "1–4 hunters · five-round PVE trial",
    title: "Rogue Trials",
    description: "Build through four randomized dual-boss rounds, defeat an unseen trio, then leave with the clear or continue into endless combat.",
    detail: "Endless mode replaces every fallen boss and tracks your best kill count",
    status: "Playable now",
  },
  dungeons: {
    eyebrow: "1–4 hunters · chosen encounter",
    title: "Dungeons",
    description: "Choose a guardian, review its mechanics, and bring a prepared healing loadout into a focused encounter.",
    detail: `${AVAILABLE_BOSS_IDS.length} animated guardians available`,
    status: "Playable now",
  },
  "roguelike-pvp": {
    eyebrow: "3v3 · mirrored expeditions",
    title: "Roguelike PvP",
    description: "Race a rival squad through shifting rooms. Send hazards across the veil while keeping your own formation alive.",
    detail: "Draft order, rival pressure, and sudden-death rules",
    status: "Mode shell ready",
  },
  "stadium-pvp": {
    eyebrow: "5v5 · objective arena",
    title: "Stadium PvP",
    description: "Bring a prepared loadout into short team battles where positioning, interrupts, and clutch healing decide the round.",
    detail: "Best of five rounds / normalized gear",
    status: "Mode shell ready",
  },
};

export function selectRandomBoss(random: () => number = Math.random): BossId {
  return AVAILABLE_BOSS_IDS[Math.floor(random() * AVAILABLE_BOSS_IDS.length)] ?? AVAILABLE_BOSS_IDS[0];
}

export const MAX_HUNTER_NAME_LENGTH = 20;

export function normalizeHunterName(value: string): string {
  return value
    .replace(/[\u0000-\u001f\u007f]/g, "")
    .replace(/\s+/g, " ")
    .trim()
    .slice(0, MAX_HUNTER_NAME_LENGTH);
}

export function createHunterSave(slotId: SaveSlotId, now: string, hunterName: string): HunterSave {
  const normalizedName = normalizeHunterName(hunterName);
  if (!normalizedName) throw new Error("Hunter name is required.");
  return {
    schemaVersion: 5,
    slotId,
    hunterName: normalizedName,
    activeClassId: "priest",
    healers: {
      priest: { level: 1, inventory: createClassInventory("priest") },
      druid: { level: 1, inventory: createClassInventory("druid") },
      shaman: { level: 1, inventory: createClassInventory("shaman") },
    },
    location: "Ember Vault Approach",
    playSeconds: 0,
    updatedAt: now,
    stats: {
      totalBossKills: 0,
      flawlessClears: 0,
      alliesSaved: 0,
      healingDone: 0,
      bossKills: {},
      highestRoguelikeRound: 0,
      highestRogueTrialsEndlessKills: 0,
    },
    materials: [] as MaterialStack[],
    collectionLog: createEmptyCollectionLog(),
    gearProgress: createDefaultGearProgress(),
  };
}
