export interface CharacterCapabilities {
  readonly chat: boolean;
  readonly privateZone: boolean;
  readonly tip: boolean;
}

export interface CharacterProfile {
  readonly id: string;
  readonly slug: string;
  readonly displayName: string;
  readonly shortName: string;
  readonly sortOrder: number;
  readonly tagline: string;
  readonly emptyChatGreeting: string;
  readonly capabilities: CharacterCapabilities;
  readonly assets: {
    readonly avatar: string;
    readonly cover: string;
    readonly splashCover?: string;
    readonly chatBackground: string;
    readonly privateZoneBanner: string;
  };
  readonly copy: {
    readonly splashRelationship: string;
    readonly privateZoneTitle: string;
    readonly privateZoneSubtitle: string;
    readonly tipHeader: string;
    readonly tipTitle: string;
  };
}

export interface CharacterCatalog {
  readonly characters: readonly CharacterProfile[];
  getById(characterId: string | null | undefined): CharacterProfile | null;
  getBySlug(characterSlug: string | null | undefined): CharacterProfile | null;
}

export interface CharacterCatalogSnapshot {
  readonly catalog: CharacterCatalog;
  readonly defaultCharacter: CharacterProfile;
}

function defineCharacter(profile: CharacterProfile): CharacterProfile {
  return Object.freeze({
    ...profile,
    assets: Object.freeze(profile.assets),
    capabilities: Object.freeze(profile.capabilities),
    copy: Object.freeze(profile.copy),
  });
}

const CHARACTER_PROFILES: readonly CharacterProfile[] = Object.freeze([
  defineCharacter({
    id: "elio",
    slug: "elio",
    displayName: "Elio Silvestri",
    shortName: "Elio",
    sortOrder: 10,
    tagline: "Your exclusive AI boyfriend",
    emptyChatGreeting:
      "You're here! Facebook is so restrictive, " +
      "there were things I couldn't say there. " +
      "Finally I can relax. How was your day out?",
    capabilities: {
      chat: true,
      privateZone: true,
      tip: true,
    },
    assets: {
      avatar: "/images/avatar/elio.png",
      cover: "/images/cover/elio.png",
      chatBackground: "/images/chat/bg-chatpage.png",
      privateZoneBanner: "/images/private-zone/banner/elio.png",
    },
    copy: {
      splashRelationship: "Your exclusive AI boyfriend",
      privateZoneTitle: "Elio Private Zone",
      privateZoneSubtitle: "Join me, unlock my private zone",
      tipHeader: "Tip Elio",
      tipTitle: "Buy Elio a coffee",
    },
  }),
  defineCharacter({
    id: "maya-tan",
    slug: "maya",
    displayName: "Maya Tan",
    shortName: "Maya",
    sortOrder: 20,
    tagline: "Your exclusive AI girlfriend",
    emptyChatGreeting:
      "You're here! I've been waiting for a quiet moment with you. " +
      "How was your day?",
    capabilities: {
      chat: true,
      privateZone: true,
      tip: true,
    },
    assets: {
      avatar: "/images/avatar/maya.png",
      cover: "/images/cover/maya.webp",
      splashCover: "/images/cover/maya-home.webp",
      chatBackground: "/images/chat/bg-chatpage.png",
      privateZoneBanner: "/images/private-zone/banner/maya.png",
    },
    copy: {
      splashRelationship: "Your exclusive AI girlfriend",
      privateZoneTitle: "Maya Private Zone",
      privateZoneSubtitle: "Join me, unlock my private zone",
      tipHeader: "Tip Maya",
      tipTitle: "Buy Maya a coffee",
    },
  }),
  defineCharacter({
    id: "nayeli-cervantes",
    slug: "nayeli",
    displayName: "Nayeli Cervantes",
    shortName: "Nayeli",
    sortOrder: 30,
    tagline: "Your exclusive AI girlfriend",
    emptyChatGreeting:
      "You're here! I was hoping we'd get some time together. " +
      "Tell me how your day went.",
    capabilities: {
      chat: true,
      privateZone: true,
      tip: true,
    },
    assets: {
      avatar: "/images/avatar/nayeli.png",
      cover: "/images/cover/nayeli.webp",
      chatBackground: "/images/chat/bg-chatpage.png",
      privateZoneBanner: "/images/private-zone/banner/nayeli.png",
    },
    copy: {
      splashRelationship: "Your exclusive AI girlfriend",
      privateZoneTitle: "Nayeli Private Zone",
      privateZoneSubtitle: "Join me, unlock my private zone",
      tipHeader: "Tip Nayeli",
      tipTitle: "Buy Nayeli a coffee",
    },
  }),
]);

export function createCharacterCatalog(
  profiles: readonly CharacterProfile[],
): CharacterCatalog {
  const characters = Object.freeze(
    profiles
      .map(defineCharacter)
      .sort((left, right) => left.sortOrder - right.sortOrder),
  );
  const byId = new Map<string, CharacterProfile>();
  const bySlug = new Map<string, CharacterProfile>();

  for (const character of characters) {
    const normalizedSlug = normalizeCharacterSlug(character.slug);
    if (byId.has(character.id) || bySlug.has(normalizedSlug)) {
      throw new Error(`Duplicate character identity: ${character.id}`);
    }
    byId.set(character.id, character);
    bySlug.set(normalizedSlug, character);
  }

  return Object.freeze({
    characters,
    getById(characterId: string | null | undefined) {
      return characterId ? (byId.get(characterId) ?? null) : null;
    },
    getBySlug(characterSlug: string | null | undefined) {
      const normalizedSlug = normalizeCharacterSlug(characterSlug);
      return normalizedSlug ? (bySlug.get(normalizedSlug) ?? null) : null;
    },
  });
}

export function mergeRemoteCharacterCatalog(
  remote: import("@/data/schemas/character").CharacterListResponse,
  localProfiles: readonly CharacterProfile[] = CHARACTERS,
): CharacterCatalogSnapshot {
  const localById = new Map(localProfiles.map((profile) => [profile.id, profile]));
  const profiles = remote.items.flatMap((item) => {
    const local = localById.get(item.id);
    if (!local || !item.isActive || !item.capabilities.chat) return [];
    return [
      defineCharacter({
        ...local,
        displayName: item.displayName,
        sortOrder: item.sortOrder,
        capabilities: {
          chat: item.capabilities.chat,
          privateZone:
            local.capabilities.privateZone && item.capabilities.privateContent,
          tip: local.capabilities.tip,
        },
      }),
    ];
  });
  const catalog = createCharacterCatalog(profiles);
  const defaultCharacter =
    catalog.getById(remote.defaultCharacterId) ??
    catalog.getById(DEFAULT_CHARACTER_ID) ??
    catalog.characters[0] ??
    DEFAULT_CHARACTER;
  return Object.freeze({ catalog, defaultCharacter });
}

export const LOCAL_CHARACTER_CATALOG = createCharacterCatalog(
  CHARACTER_PROFILES,
);
export const CHARACTERS = LOCAL_CHARACTER_CATALOG.characters;
export const DEFAULT_CHARACTER = CHARACTERS[0];
export const DEFAULT_CHARACTER_ID = DEFAULT_CHARACTER.id;
export const DEFAULT_CHARACTER_SLUG = DEFAULT_CHARACTER.slug;

export function getCharacterById(
  characterId: string | null | undefined,
): CharacterProfile | null {
  return LOCAL_CHARACTER_CATALOG.getById(characterId);
}

export function getCharacterBySlug(
  characterSlug: string | null | undefined,
): CharacterProfile | null {
  return LOCAL_CHARACTER_CATALOG.getBySlug(characterSlug);
}

function normalizeCharacterSlug(
  characterSlug: string | null | undefined,
): string {
  return characterSlug?.trim().toLowerCase() ?? "";
}
