/**
 * Free-text creation attribute keys come from the legacy DB exactly as they were
 * typed in — including misspellings, doubled/leading spaces and near-duplicates
 * (e.g. `Alkotás eredméye`, `' Alkotó szerepe'`). Until the data is cleaned up,
 * this helper maps every known raw key onto a single, correctly spelled group so
 * the creation page can display and order them sensibly.
 *
 * IMPORTANT: the strings in `keys` must stay byte-for-byte identical to what is
 * stored in the DB (leading spaces, double spaces, typos included) — they are the
 * lookup keys. Only `label` is the cleaned-up text we actually show.
 *
 * Display buckets follow the editorial "ki? / mit? / hol?" ordering:
 *   - `who`   – people & roles (ki?)        e.g. Alkotó szerepe, Szerző
 *   - `what`  – nature/result/medium (mit?) e.g. Alkotás eredménye, Alkotás jellege
 *   - `where` – place & institution (hol?)  e.g. Kiadás helye, Intézmény neve
 *   - `other` – anything not yet classified (always shown last)
 */

export type CreationAttributeCategory = 'who' | 'what' | 'where' | 'other';

export interface CreationAttributeGroup {
  /** Cleaned-up, correctly spelled label shown in the UI (Hungarian). */
  label: string;
  /** English label for the same attribute — hardcoded because the DB only stores Hungarian keys. */
  labelEn?: string;
  /** Display bucket (ki? / mit? / hol?). */
  category: CreationAttributeCategory;
  /** Exact raw DB keys that belong to this group — kept verbatim, typos and all. */
  keys: string[];
}

/** Order in which the category buckets are rendered. */
export const CREATION_ATTRIBUTE_CATEGORY_ORDER: CreationAttributeCategory[] = [
  'who',
  'what',
  'where',
  'other',
];

/**
 * Source of truth for grouping. Order within each category is the intended
 * display order (roughly by how common / important the field is). Add new raw
 * keys to the matching group's `keys` as they surface in the data.
 */
export const CREATION_ATTRIBUTE_GROUPS: CreationAttributeGroup[] = [
  // ── ki? — people & roles ──────────────────────────────────────────────────
  {
    label: 'Alkotó szerepe',
    labelEn: "Creator's role",
    category: 'who',
    keys: [
      'Alkotó szerepe',
      ' Alkotó szerepe',
      'Aélotó szerepe',
      'Akjotó szerepe',
      'Akotó szerepe',
      'Alkotá szerepe',
      'Alkotás szerepe',
      'Alkotó szeepe',
      'Alkotó szerep',
      'Alotó szerepe',
    ],
  },
  {
    label: 'Szerző',
    labelEn: 'Author',
    category: 'who',
    keys: ['Szerző'],
  },
  {
    label: 'Rendező',
    labelEn: 'Director',
    category: 'who',
    keys: ['Rendező', 'Randező'],
  },
  {
    label: 'Szerep neve',
    labelEn: 'Character name',
    category: 'who',
    keys: ['Szerep neve'],
  },
  {
    label: 'Szerep',
    labelEn: 'Character',
    category: 'who',
    keys: ['Szerep'],
  },
  {
    label: 'Kapcsolódó szerző',
    labelEn: 'Related author',
    category: 'who',
    keys: ['Kapcsolódó szerző'],
  },
  {
    label: 'Alkotótárs',
    labelEn: 'Co-creator',
    category: 'who',
    keys: ['Alkotótárs', 'Alkotóttárs'],
  },
  {
    label: 'Borítótervező',
    labelEn: 'Cover designer',
    category: 'who',
    keys: ['Borítótervező'],
  },
  {
    label: 'Díszlettervező',
    labelEn: 'Set designer',
    category: 'who',
    keys: ['Díszlettervező'],
  },
  {
    label: 'Forgatókönyvíró',
    labelEn: 'Screenwriter',
    category: 'who',
    keys: ['Forgatókönyvíró'],
  },
  {
    label: 'Koreográfus',
    labelEn: 'Choreographer',
    category: 'who',
    keys: ['Koreográfus'],
  },
  {
    label: 'Operatőr',
    labelEn: 'Cinematographer',
    category: 'who',
    keys: ['Operatőr'],
  },
  {
    label: 'Akadémikus szerepe',
    labelEn: 'Academic role',
    category: 'who',
    keys: ['Akadémikus szerepe'],
  },

  // ── mit? — nature / result / medium ───────────────────────────────────────
  {
    label: 'Alkotás eredménye',
    labelEn: 'Result of work',
    category: 'what',
    keys: [
      'Alkotás eredménye',
      ' Alkotás eredménye',
      'Akotás eredménye',
      'Alkorás eredménye',
      'Alkortás eredménye',
      'Alkotáas eredménye',
      'Alkotás eredémye',
      'Alkotás eredmémye',
      'Alkotás eredmény',
      'Alkotás eredményw',
      'Alkotás eredméye',
      'Alkotás eredméyne',
      'Alkotás ereménye',
      'Alkotás-eredménye',
      'Alkotós eredménye',
      'Alkotűs eredménye',
      'Alktás eredménye',
      'Alkutás eredménye',
    ],
  },
  {
    label: 'Méret',
    labelEn: 'Size',
    category: 'what',
    keys: ['Méret'],
  },
  {
    label: 'Alkotás anyaga',
    labelEn: 'Material',
    category: 'what',
    keys: ['Alkotás anyaga', 'Akotás anyaga'],
  },
  {
    label: 'Zeneművészeti alkotás jellege',
    labelEn: 'Nature of musical work',
    category: 'what',
    keys: ['Zeneművészeti alkotás jellege'],
  },
  {
    label: 'Technika',
    labelEn: 'Technique',
    category: 'what',
    keys: ['Technika'],
  },
  {
    label: 'Nyelv',
    labelEn: 'Language',
    category: 'what',
    keys: ['Nyelv'],
  },
  {
    label: 'Hordozó típusa',
    labelEn: 'Medium type',
    category: 'what',
    keys: ['Hordozó típusa'],
  },
  {
    label: 'Építészeti alkotás státusza',
    labelEn: 'Status of architectural work',
    category: 'what',
    keys: ['Építészeti alkotás státusza'],
  },
  {
    label: 'Építészeti alkotás funkciócsoportja',
    labelEn: 'Function group of architectural work',
    category: 'what',
    keys: ['Építészeti alkotás funkciócsoportja'],
  },
  {
    label: 'Műfaj',
    labelEn: 'Genre',
    category: 'what',
    keys: ['Műfaj'],
  },
  {
    label: 'Film műfaja',
    labelEn: 'Film genre',
    category: 'what',
    keys: ['Film műfaja'],
  },
  {
    label: 'Terjedelem',
    labelEn: 'Extent',
    category: 'what',
    keys: ['Terjedelem'],
  },
  {
    label: 'Iparművészeti alkotás mérete',
    labelEn: 'Size of applied art work',
    category: 'what',
    keys: ['Iparművészeti alkotás mérete'],
  },
  {
    label: 'Köztéri alkotás',
    labelEn: 'Public artwork',
    category: 'what',
    keys: ['Köztéri alkotás'],
  },
  {
    label: 'Zeneművészeti alkotás típusa',
    labelEn: 'Type of musical work',
    category: 'what',
    keys: ['Zeneművészeti alkotás típusa'],
  },
  {
    label: 'Iparművészeti alkotás technikája',
    labelEn: 'Technique of applied art work',
    category: 'what',
    // NB: the raw key has a double space between the first two words.
    keys: ['Iparművészeti  alkotás technikája'],
  },
  {
    label: 'Alkotás jellege',
    labelEn: 'Nature of work',
    category: 'what',
    keys: ['Alkotás jellege'],
  },
  {
    label: 'Sorozat',
    labelEn: 'Series',
    category: 'what',
    keys: ['Sorozat'],
  },
  {
    label: 'Sorozatcím',
    labelEn: 'Series title',
    category: 'what',
    keys: ['Sorozatcím'],
  },
  {
    label: 'Alkotás technikája',
    labelEn: 'Technique of work',
    category: 'what',
    keys: ['Alkotás technikája'],
  },
  {
    label: 'Fejezetcím',
    labelEn: 'Chapter title',
    category: 'what',
    keys: ['Fejezetcím'],
  },
  {
    label: 'Fejezet',
    labelEn: 'Chapter',
    category: 'what',
    keys: ['Fejezet'],
  },
  {
    label: 'Kiadás száma',
    labelEn: 'Edition number',
    category: 'what',
    keys: ['Kiadás száma'],
  },
  {
    label: 'Kiadás',
    labelEn: 'Edition',
    category: 'what',
    keys: ['Kiadás'],
  },
  {
    label: 'Kiadás éve',
    labelEn: 'Year of publication',
    category: 'what',
    keys: ['Kiadás éve'],
  },
  {
    label: 'Alkotás kategóriája',
    labelEn: 'Category of work',
    category: 'what',
    keys: ['Alkotás kategóriája'],
  },
  {
    label: 'Fotóművészeti alkotás jellege',
    labelEn: 'Nature of photographic work',
    category: 'what',
    keys: ['Fotóművészeti alkotás jellege'],
  },
  {
    label: 'Fotóművészeti alkotás tárgya',
    labelEn: 'Subject of photographic work',
    category: 'what',
    keys: ['Fotóművészeti alkotás tárgya'],
  },
  {
    label: 'Fotóművészeti alkotás technikája',
    labelEn: 'Technique of photographic work',
    category: 'what',
    keys: ['Fotóművészeti alkotás technikája'],
  },
  {
    label: 'Fotóművészeti alkotás típusa',
    labelEn: 'Type of photographic work',
    category: 'what',
    keys: ['Fotóművészeti alkotás típusa'],
  },
  {
    label: 'Fotó mérete',
    labelEn: 'Photo size',
    category: 'what',
    keys: ['Fotó mérete'],
  },
  {
    label: 'Előadott mű címe',
    labelEn: 'Title of performed work',
    category: 'what',
    keys: ['Előadott mű címe'],
  },
  {
    label: 'Oldalszám',
    labelEn: 'Page count',
    category: 'what',
    keys: ['Oldalszám'],
  },
  {
    label: 'Hossz',
    labelEn: 'Length',
    category: 'what',
    keys: ['Hossz'],
  },
  {
    label: 'Alkotás státusza',
    labelEn: 'Status of work',
    category: 'what',
    keys: ['Alkotás státusza'],
  },
  {
    label: 'Alkotás stílusa',
    labelEn: 'Style of work',
    category: 'what',
    keys: ['Alkotás stílusa'],
  },
  {
    label: 'Epizódszám',
    labelEn: 'Episode number',
    category: 'what',
    keys: ['Epizódszám'],
  },
  {
    label: 'Akadémikus szerepe eredménye',
    labelEn: 'Result of academic role',
    category: 'what',
    keys: ['Akadémikus szerepe eredménye'],
  },
  {
    label: 'Filmtechnika',
    labelEn: 'Film technique',
    category: 'what',
    keys: ['Filmtechnika'],
  },
  {
    label: 'Filmművészeti alkotás státusza',
    labelEn: 'Status of film work',
    category: 'what',
    keys: ['Filmművészti alkotás státusza'],
  },
  {
    label: 'Iparművészeti alkotás státusza',
    labelEn: 'Status of applied art work',
    category: 'what',
    keys: ['Iparművészeti alkotás státusza'],
  },
  {
    label: 'Kiadvány nyelve',
    labelEn: 'Language of publication',
    category: 'what',
    keys: ['Kiadvány nyelve'],
  },

  // ── hol? — place & institution ────────────────────────────────────────────
  {
    label: 'Kiadás helye',
    labelEn: 'Place of publication',
    category: 'where',
    keys: ['Kiadás helye'],
  },
  {
    label: 'Kiadó',
    labelEn: 'Publisher',
    category: 'where',
    keys: ['Kiadó', 'Kiadó neve'],
  },
  {
    label: 'Intézmény neve',
    labelEn: 'Institution',
    category: 'where',
    keys: ['Intézmény neve', 'IIntézmény neve'],
  },
  {
    label: 'Gyártó stúdió',
    labelEn: 'Production studio',
    category: 'where',
    keys: ['Gyártó stúdió'],
  },
  {
    label: 'Intézmény, alszervezet',
    labelEn: 'Institution, sub-unit',
    category: 'where',
    keys: ['Intézmény, alszervezet'],
  },
  {
    label: 'Megjelenés helye',
    labelEn: 'Place of release',
    category: 'where',
    keys: ['Megjelenés helye'],
  },

  // ── egyéb — unnamed / unclassified (always shown last) ─────────────────────
  {
    // The DB stores attributes with no name as the literal key `NULL`. We still
    // want to see their values, so they land here at the very end.
    label: 'Egyéb',
    labelEn: 'Other',
    category: 'other',
    keys: ['NULL'],
  },
];

/** Precomputed `rawKey -> group` lookup, plus each group's display rank. */
const groupByKey = new Map<string, CreationAttributeGroup>();
const rankByGroup = new Map<CreationAttributeGroup, number>();

CREATION_ATTRIBUTE_GROUPS.forEach((group, index) => {
  rankByGroup.set(group, index);
  group.keys.forEach((key) => groupByKey.set(key, group));
});

const categoryRank = (category: CreationAttributeCategory): number => {
  const rank = CREATION_ATTRIBUTE_CATEGORY_ORDER.indexOf(category);
  return rank === -1 ? CREATION_ATTRIBUTE_CATEGORY_ORDER.length : rank;
};

/**
 * Resolve a raw DB key to its group. Falls back to a trimmed match (handles
 * unforeseen leading/trailing whitespace), and finally to a synthetic `other`
 * group using the raw key as its own label so nothing is silently dropped.
 * Null/empty keys (the DB sometimes has no attribute name) land in `Egyéb`.
 */
export const getCreationAttributeGroup = (
  rawKey: string | null | undefined
): CreationAttributeGroup => {
  const key = (rawKey ?? '').trim();
  if (!key) return { label: 'Egyéb', category: 'other', keys: [] };

  const direct = groupByKey.get(rawKey as string);
  if (direct) return direct;

  const trimmed = groupByKey.get(key);
  if (trimmed) return trimmed;

  return { label: key, category: 'other', keys: [rawKey as string] };
};

/** Cleaned-up, display-ready label for a raw DB key. Pass `locale` to get English when not 'hu'. */
export const getCreationAttributeLabel = (
  rawKey: string | null | undefined,
  locale?: string
): string => {
  const group = getCreationAttributeGroup(rawKey);
  if (locale && locale !== 'hu' && group.labelEn) return group.labelEn;
  return group.label;
};

/** Display bucket (ki? / mit? / hol? / other) for a raw DB key. */
export const getCreationAttributeCategory = (
  rawKey: string | null | undefined
): CreationAttributeCategory => getCreationAttributeGroup(rawKey).category;

/**
 * Comparator for raw attribute keys: orders by category (ki? → mit? → hol? →
 * other), then by the intended in-category order, then alphabetically by label
 * for anything unranked. Use with `Array.prototype.sort`.
 *
 * @example attributes.sort(compareCreationAttributeKeys)
 */
export const compareCreationAttributeKeys = (
  aKey: string | null | undefined,
  bKey: string | null | undefined
): number => {
  const a = getCreationAttributeGroup(aKey);
  const b = getCreationAttributeGroup(bKey);

  const byCategory = categoryRank(a.category) - categoryRank(b.category);
  if (byCategory !== 0) return byCategory;

  const aRank = rankByGroup.get(a) ?? Number.MAX_SAFE_INTEGER;
  const bRank = rankByGroup.get(b) ?? Number.MAX_SAFE_INTEGER;
  if (aRank !== bRank) return aRank - bRank;

  return a.label.localeCompare(b.label, 'hu');
};
