import type { Rgb } from "../image/Raster.js";
import { SKIN } from "./body.js";
import type { CharacterRecipe, CreatorPalette } from "./types.js";

const rgb = (r: number, g: number, b: number): Rgb => ({ r, g, b });

function palette(partial: Partial<CreatorPalette> & Pick<CreatorPalette, "skin" | "hair">): CreatorPalette {
  return {
    primary: rgb(70, 75, 55),
    secondary: rgb(45, 48, 52),
    accent: rgb(120, 100, 60),
    metal: rgb(140, 140, 145),
    leather: rgb(70, 50, 35),
    ...partial,
  };
}

/**
 * Game cast as modular outfits. Add a recipe, run `pnpm cast`, get a GLB.
 */
export const CHARACTER_PRESETS: CharacterRecipe[] = [
  {
    id: "survivor",
    name: "Survivor",
    body: "male",
    height: 1.72,
    // Wiry survivor — lean, a bit of muscle.
    bodyStyle: { mass: -0.25, muscle: 0.2, fat: 0.05 },
    // Gaunt and long-featured — the face the player looks at most.
    headStyle: { length: 0.45, jaw: 0.15, brow: 0.3 },
    styleNotes:
      "olive drab field jacket over a grey tee, dirt-worn canvas cargo trousers, " +
      "scuffed brown leather boots, dried mud at the hems, stubble",

    palette: palette({
      skin: SKIN.medium,
      hair: rgb(40, 36, 32),
      primary: rgb(78, 82, 52),
      secondary: rgb(48, 50, 55),
      accent: rgb(90, 70, 40),
      leather: rgb(85, 60, 40),
    }),
    parts: {
      hair: "hair.short",
      upper: "upper.jacket",
      lower: "lower.cargo",
      feet: "feet.boots",
      accessory: "accessory.backpack",
    },
  },
  {
    id: "researcher",
    name: "Dr. Hale",
    body: "female",
    height: 1.66,
    bodyStyle: { mass: -0.15, muscle: -0.1, fat: 0.05 },
    // Fine-boned, neutral length — reads academic next to the others.
    headStyle: { length: 0.2, jaw: -0.35, brow: -0.2 },
    styleNotes:
      "clean off-white lab coat over a navy blouse and slim charcoal trousers, " +
      "plain black flats, wire-rimmed glasses, no weathering",

    palette: palette({
      skin: SKIN.fair,
      hair: rgb(200, 190, 175),
      primary: rgb(230, 228, 220),
      secondary: rgb(50, 52, 65),
      accent: rgb(80, 90, 110),
      leather: rgb(60, 50, 45),
    }),
    parts: {
      hair: "hair.bun",
      upper: "upper.labcoat",
      lower: "lower.pants",
      feet: "feet.shoes",
      accessory: "accessory.glasses",
    },
    partColors: {
      "upper.labcoat": rgb(235, 233, 225),
    },
  },
  {
    id: "officer",
    name: "Sgt. Marrow",
    body: "male",
    height: 1.82,
    // Built cop — heavier mass + muscle.
    bodyStyle: { mass: 0.35, muscle: 0.45, fat: 0.1 },
    // Slab of a head: short, square, heavy brow.
    headStyle: { length: -0.35, jaw: 0.8, brow: 0.65 },
    styleNotes:
      "dark slate police uniform, brass buttons and a gold shoulder flash, " +
      "black duty belt, polished black boots, crisp and pressed",

    palette: palette({
      skin: SKIN.tan,
      hair: rgb(28, 28, 30),
      primary: rgb(38, 50, 46),
      secondary: rgb(32, 36, 40),
      accent: rgb(160, 140, 50),
      leather: rgb(35, 30, 28),
    }),
    parts: {
      hair: "hair.undercut",
      upper: "upper.uniform",
      lower: "lower.pants",
      feet: "feet.boots",
      accessory: "accessory.belt",
    },
  },
  {
    id: "groundskeeper",
    name: "Ellis",
    body: "male",
    height: 1.75,
    // Soft bulk from outdoor work / beer.
    bodyStyle: { mass: 0.2, muscle: 0.1, fat: 0.35 },
    // Round and jowly to match the soft bulk.
    headStyle: { length: -0.5, jaw: 0.3, brow: 0.1 },
    styleNotes:
      "faded rust-brown work coat, heavy tan canvas trousers, oil stains at the " +
      "knees and cuffs, worn steel-toe boots",

    palette: palette({
      skin: SKIN.tan,
      hair: rgb(90, 70, 50),
      primary: rgb(120, 78, 48),
      secondary: rgb(70, 72, 78),
      accent: rgb(100, 80, 50),
      leather: rgb(55, 45, 35),
    }),
    parts: {
      hair: "hair.messy",
      upper: "upper.workcoat",
      lower: "lower.cargo",
      feet: "feet.boots",
      accessory: "accessory.satchel",
    },
  },
  // Extra starter outfits — ready for new NPCs / player variants.
  {
    id: "civilian-f",
    name: "Civilian",
    body: "female",
    height: 1.64,
    bodyStyle: { mass: 0, muscle: -0.05, fat: 0.1 },
    headStyle: { length: -0.15, jaw: 0.1, brow: 0.15 },
    styleNotes:
      "muted plum wool overcoat, dark knee-length skirt, black tights, simple " +
      "low-heeled shoes, everyday and unremarkable",

    palette: palette({
      skin: SKIN.light,
      hair: rgb(55, 35, 28),
      primary: rgb(90, 70, 95),
      secondary: rgb(50, 48, 55),
      leather: rgb(80, 55, 45),
    }),
    parts: {
      hair: "hair.long",
      upper: "upper.coat",
      lower: "lower.skirt",
      feet: "feet.shoes",
      accessory: "accessory.none",
    },
  },
  {
    id: "civilian-m",
    name: "Townsman",
    body: "male",
    height: 1.76,
    bodyStyle: { mass: 0.05, muscle: 0, fat: 0.15 },
    headStyle: { length: 0.1, jaw: -0.2, brow: -0.35 },
    styleNotes:
      "charcoal two-piece business suit, white dress shirt, burgundy tie, " +
      "polished black oxfords, slightly rumpled after a long day",

    palette: palette({
      skin: SKIN.light,
      hair: rgb(70, 60, 50),
      primary: rgb(95, 90, 85),
      secondary: rgb(55, 55, 60),
      leather: rgb(65, 48, 38),
    }),
    parts: {
      hair: "hair.short",
      upper: "upper.shirt",
      lower: "lower.pants",
      feet: "feet.shoes",
      accessory: "accessory.belt",
    },
  },
];

export function presetById(id: string): CharacterRecipe | undefined {
  return CHARACTER_PRESETS.find((preset) => preset.id === id);
}
