import type { HealerClassId, MemberId } from "./types";
import {
  cloneCharacterAppearance,
  normalizeCharacterAppearance,
  type CharacterAppearanceV1,
  type CharacterHeldItemVisual,
  type CharacterWeaponGrip,
  type CharacterWeaponModelId,
} from "./characterAppearance";

export type HealerWeaponModelId = CharacterWeaponModelId;
export type HealerWeaponGrip = CharacterWeaponGrip;
export type HealerAccessoryId = "sun-halo" | "grove-antlers" | "storm-totem" | "sun-crest" | "clockwork-rings";

export type HealerHeldItemVisual = CharacterHeldItemVisual;

export interface HealerVisualProfile {
  /** Geometry source. Every source uses the shared Rig_Medium bone contract. */
  bodyMemberId: MemberId;
  /** Aelia's Druid file remains the single animation source for every healer. */
  animationMemberId: "aelia";
  appearance: CharacterAppearanceV1;
  hiddenNodes: readonly string[];
  accessory: HealerAccessoryId;
  accentColor: string;
  secondaryColor: string;
}

export const HEALER_VISUAL_PROFILES: Record<HealerClassId, HealerVisualProfile> = {
  priest: {
    bodyMemberId: "orin",
    animationMemberId: "aelia",
    appearance: {
      version: 1,
      rigId: "medium",
      scaleSourceMemberId: "orin",
      headPartId: "priest-head",
      upperBodyPartId: "priest-upper",
      lowerBodyPartId: "priest-lower",
      headwearPartId: null,
      backPartId: "priest-cape",
      mainHand: { modelId: "cc/adv_druid_staff", grip: "staff" },
    },
    hiddenNodes: ["Mage_Hat"],
    accessory: "sun-halo",
    accentColor: "#ffe7a3",
    secondaryColor: "#8bd8ff",
  },
  druid: {
    bodyMemberId: "aelia",
    animationMemberId: "aelia",
    appearance: {
      version: 1,
      rigId: "medium",
      scaleSourceMemberId: "aelia",
      headPartId: "druid-head",
      upperBodyPartId: "druid-upper",
      lowerBodyPartId: "druid-lower",
      headwearPartId: null,
      backPartId: "druid-backpack",
      mainHand: { modelId: "cc/adv_druid_staff", grip: "staff" },
    },
    hiddenNodes: [],
    accessory: "grove-antlers",
    accentColor: "#79d66f",
    secondaryColor: "#e8b86a",
  },
  shaman: {
    bodyMemberId: "nia",
    animationMemberId: "aelia",
    appearance: {
      version: 1,
      rigId: "medium",
      scaleSourceMemberId: "nia",
      headPartId: "ranger-head",
      upperBodyPartId: "ranger-upper",
      lowerBodyPartId: "ranger-lower",
      headwearPartId: null,
      backPartId: "ranger-cape",
      mainHand: { modelId: "cc/adv_druid_staff", grip: "staff" },
    },
    hiddenNodes: ["Ranger_Quiver"],
    accessory: "storm-totem",
    accentColor: "#62bdff",
    secondaryColor: "#7de0bf",
  },
  paladin: {
    bodyMemberId: "brann",
    animationMemberId: "aelia",
    appearance: {
      version: 1,
      rigId: "medium",
      scaleSourceMemberId: "brann",
      headPartId: "knight-head",
      upperBodyPartId: "knight-upper",
      lowerBodyPartId: "knight-lower",
      headwearPartId: "knight-helmet",
      backPartId: "knight-cape",
      mainHand: { modelId: "cc/hammer_a", grip: "upright" },
      offHand: { modelId: "cc/shield_badge", grip: "prop" },
    },
    hiddenNodes: [],
    accessory: "sun-crest",
    accentColor: "#ffc45c",
    secondaryColor: "#fff3bd",
  },
  chronomancer: {
    bodyMemberId: "vale",
    animationMemberId: "aelia",
    appearance: {
      version: 1,
      rigId: "medium",
      scaleSourceMemberId: "vale",
      headPartId: "rogue-head",
      upperBodyPartId: "rogue-upper",
      lowerBodyPartId: "rogue-lower",
      headwearPartId: null,
      backPartId: "rogue-cape",
      mainHand: { modelId: "cc/adv_wand", grip: "wand" },
      offHand: { modelId: "cc/spellbook_open", grip: "prop" },
    },
    hiddenNodes: [],
    accessory: "clockwork-rings",
    accentColor: "#62d4d9",
    secondaryColor: "#8877ff",
  },
};

const LEGACY_HEALER_DEFAULTS: Partial<Record<HealerClassId, CharacterAppearanceV1>> = {
  priest: {
    version: 1,
    rigId: "medium",
    scaleSourceMemberId: "orin",
    headPartId: "mage-head",
    upperBodyPartId: "mage-upper",
    lowerBodyPartId: "mage-lower",
    headwearPartId: null,
    backPartId: "mage-cape",
    mainHand: { modelId: "cc/adv_druid_staff", grip: "staff" },
  },
  paladin: {
    version: 1,
    rigId: "medium",
    scaleSourceMemberId: "brann",
    headPartId: "knight-head",
    upperBodyPartId: "knight-upper",
    lowerBodyPartId: "knight-lower",
    headwearPartId: "knight-helmet",
    backPartId: "knight-cape",
    mainHand: { modelId: "cc/adv_sword_1handed", grip: "upright" },
    offHand: { modelId: "cc/shield_badge", grip: "prop" },
  },
};

function appearancesMatch(left: CharacterAppearanceV1, right: CharacterAppearanceV1) {
  return left.version === right.version
    && left.rigId === right.rigId
    && left.scaleSourceMemberId === right.scaleSourceMemberId
    && left.headPartId === right.headPartId
    && left.upperBodyPartId === right.upperBodyPartId
    && left.lowerBodyPartId === right.lowerBodyPartId
    && left.headwearPartId === right.headwearPartId
    && left.backPartId === right.backPartId
    && left.mainHand.modelId === right.mainHand.modelId
    && left.offHand?.modelId === right.offHand?.modelId;
}

export function createDefaultHealerAppearance(classId: HealerClassId): CharacterAppearanceV1 {
  return cloneCharacterAppearance(HEALER_VISUAL_PROFILES[classId].appearance);
}

export function normalizeHealerAppearance(classId: HealerClassId, value: unknown): CharacterAppearanceV1 {
  const normalized = normalizeCharacterAppearance(value, HEALER_VISUAL_PROFILES[classId].appearance);
  const legacyDefault = LEGACY_HEALER_DEFAULTS[classId];
  return legacyDefault && appearancesMatch(normalized, legacyDefault)
    ? createDefaultHealerAppearance(classId)
    : normalized;
}

export function healerVisualSignature(profile: HealerVisualProfile) {
  return [
    profile.appearance.headPartId,
    profile.appearance.upperBodyPartId,
    profile.appearance.lowerBodyPartId,
    profile.appearance.headwearPartId ?? "bare",
    profile.appearance.backPartId ?? "no-back",
    profile.accessory,
    profile.appearance.mainHand.modelId,
    profile.appearance.offHand?.modelId ?? "empty",
  ].join(":");
}
