export const ROAD_SPRITE_KEY = 'terrain.road.v1';
const DEFAULT_TERRAIN_KEY = 'terrain.grass.v1';
const HERO_MODEL_VARIANTS = [0, 1, 2] as const;

/** Wilderness rest: separate props (transparent PNG), tent ~30px art height. */
export const CAMP_TENT_TEXTURE_KEY = 'prop.camp_tent.v0';
export const CAMP_FIRE_TEXTURE_KEY = 'prop.camp_fire.v0';
export const CAMP_BAG_TEXTURE_KEY = 'prop.camp_bag.v0';

const TERRAIN_TEXTURE_BY_KEY: Record<string, string> = {
  plaza: 'terrain.plaza.v1',
  road: ROAD_SPRITE_KEY,
  dirt: 'terrain.dirt.v1',
  stone: 'terrain.stone.v1',
  forest_floor: 'terrain.forest_floor.v1',
  ruins_floor: 'terrain.ruins_floor.v1',
  canyon_floor: 'terrain.canyon_floor.v1',
  swamp_floor: 'terrain.swamp_floor.v1',
  volcanic_floor: 'terrain.volcanic_floor.v1',
  astral_floor: 'terrain.astral_floor.v1',
  grass: DEFAULT_TERRAIN_KEY,
};

const OBJECT_TEXTURE_BY_KEY: Record<string, { v0: string; v1: string }> = {
  tree: { v0: 'prop.tree.v0', v1: 'prop.tree.v1' },
  rock: { v0: 'prop.rock.v0', v1: 'prop.rock.v1' },
  cart: { v0: 'prop.cart.v0', v1: 'prop.cart.v1' },
  barrel: { v0: 'prop.barrel.v0', v1: 'prop.barrel.v1' },
  bush: { v0: 'prop.bush.v0', v1: 'prop.bush.v1' },
  mushroom: { v0: 'prop.mushroom.v0', v1: 'prop.mushroom.v1' },
  leaves: { v0: 'prop.leaves.v0', v1: 'prop.leaves.v1' },
  stump: { v0: 'prop.stump.v0', v1: 'prop.stump.v1' },
  bones: { v0: 'prop.bones.v0', v1: 'prop.bones.v1' },
  ruin: { v0: 'prop.ruin.v0', v1: 'prop.ruin.v1' },
};

const NPC_TEXTURE_BY_TYPE: Record<string, string> = {
  merchant: 'npc.merchant',
  armorer: 'npc.armorer',
  weapon: 'npc.weapon',
  jeweler: 'npc.jeweler',
  healer: 'npc.healer',
  bounty_hunter: 'npc.bounty_hunter',
  elder: 'npc.elder',
  quest_giver: 'npc.quest_giver',
};

/** Town hall / civic building offset from plaza (not a `town_buildings` row). */
export const TOWN_HALL_TEXTURE_KEY = 'building.civic.townhall.v0';
/** Plaza center feature: DB uses `decoration.well` at (0,0) for the central water feature. */
export const PLAZA_FOUNTAIN_TEXTURE_KEY = 'prop.fountain.plaza.v0';
export const MARKET_STALL_TEXTURE_KEY = 'prop.market.stall.v0';

/** Generic facades for procedural town rings (no `town_buildings` rows). */
export const PROCEDURAL_TOWN_HOUSE_FACADE_KEYS = [
  'building.house.v0',
  'building.house.v1',
  'building.house.v2',
] as const;

const BUILDING_TEXTURE_BY_TYPE: Record<string, string> = {
  'house.quest_giver': 'building.house.v0',
  'house.merchant': 'building.tavern.v0',
  'house.armorer': 'building.house.v1',
  'house.weapon_smith': 'building.tavern.v1',
  'house.jeweler': 'building.house.v2',
  'house.bounty_hunter': 'building.house.v1',
  'house.elder': 'building.house.v0',
  'house.healer': 'building.house.v2',
  /** Town square feature — rendered as fountain art (see PLAZA_FOUNTAIN_TEXTURE_KEY). */
  'decoration.well': PLAZA_FOUNTAIN_TEXTURE_KEY,
  'decoration.stall': MARKET_STALL_TEXTURE_KEY,
};

export function terrainToTextureKey(terrain: string): string {
  return TERRAIN_TEXTURE_BY_KEY[terrain] ?? DEFAULT_TERRAIN_KEY;
}

export function objectToTextureKey(obj: string, variant: number): string | null {
  const entry = OBJECT_TEXTURE_BY_KEY[obj];
  if (!entry) return null;
  return variant > 0.5 ? entry.v1 : entry.v0;
}

export function npcTypeToTextureKey(npcType: string): string | null {
  return NPC_TEXTURE_BY_TYPE[npcType] ?? null;
}

export function buildingTypeToTextureKey(buildingType: string): string | null {
  return BUILDING_TEXTURE_BY_TYPE[buildingType] ?? null;
}

export function heroTextureKey(modelVariant: number, facing: 'south' | 'north'): string {
  const variant = Number.isInteger(modelVariant) && modelVariant >= 0 && modelVariant <= 2
    ? modelVariant
    : 0;
  return `hero.player.v${variant}.${facing}`;
}

export function restCampTextureKeys(): [string, string, string] {
  return [CAMP_TENT_TEXTURE_KEY, CAMP_FIRE_TEXTURE_KEY, CAMP_BAG_TEXTURE_KEY];
}

/**
 * Normalizes `enemies.type` for texture keys: trim, lowercase, strip accidental `enemy.` / `.south`.
 */
export function normalizeEnemyTemplateSlug(slug: string): string {
  let s = String(slug).trim().toLowerCase().replace(/\s+/g, '_');
  if (s.startsWith('enemy.')) s = s.slice(6);
  if (s.endsWith('.south')) s = s.slice(0, -6);
  return s;
}

/** South-facing manifest key for a template slug (`enemy.<slug>.south`). */
export function enemySouthTextureKey(slug: string): string {
  return `enemy.${normalizeEnemyTemplateSlug(slug)}.south`;
}

/** If exact south PNG is missing from the bundle, try another bandit variant (same archetype art). */
const BANDIT_SOUTH_FALLBACK_SLUGS: readonly string[] = [
  'bandit_l8_9_canyon',
  'bandit_l10_11_canyon',
  'bandit_l8_9_ruins',
  'bandit_l6_7_ruins',
  'bandit_l6_7_forest',
  'bandit_l4_5_forest',
  'bandit_l4_5_meadow',
  'bandit_l10_11_swamp',
  'bandit_l12_12_volcanic',
  'bandit_l12_12_astral',
];

/**
 * Resolves a loaded south-facing enemy texture key, or null to use procedural fallback.
 */
export function resolveEnemySouthTextureKey(
  slug: string,
  getTexture: (manifestKey: string) => unknown | null,
): string | null {
  const norm = normalizeEnemyTemplateSlug(slug);
  const trySlug = (templateSlug: string): string | null => {
    const withSouth = `enemy.${templateSlug}.south`;
    if (getTexture(withSouth) != null) return withSouth;
    const bare = `enemy.${templateSlug}`;
    return getTexture(bare) != null ? bare : null;
  };

  const primary = trySlug(norm);
  if (primary) return primary;

  if (!norm.includes('bandit')) return null;

  for (const s of BANDIT_SOUTH_FALLBACK_SLUGS) {
    if (s === norm) continue;
    const k = trySlug(s);
    if (k) return k;
  }
  return null;
}

export function getRequiredSpriteKeys(): string[] {
  const terrainKeys = Object.values(TERRAIN_TEXTURE_BY_KEY);
  const objectKeys = Object.values(OBJECT_TEXTURE_BY_KEY).flatMap((entry) => [
    entry.v0,
    entry.v1,
  ]);
  const npcKeys = Object.values(NPC_TEXTURE_BY_TYPE);
  const buildingKeys = Object.values(BUILDING_TEXTURE_BY_TYPE);
  return [
    ...new Set([
      ...terrainKeys,
      ...objectKeys,
      ...npcKeys,
      ...buildingKeys,
      TOWN_HALL_TEXTURE_KEY,
      ...HERO_MODEL_VARIANTS.flatMap((v) => [`hero.player.v${v}.south`, `hero.player.v${v}.north`]),
      CAMP_TENT_TEXTURE_KEY,
      CAMP_FIRE_TEXTURE_KEY,
      CAMP_BAG_TEXTURE_KEY,
    ]),
  ];
}
