import { normalizePdfText } from '@/components/pdf/pdfUtils';

import { CreationListItem } from '@/types/Creation';

export type CreatorLifeEventPdfItem = {
  dateLabel: string;
  key: string;
  location: string;
  title: string;
};

export type CreatorLifeEventPdfGroup = {
  events: CreatorLifeEventPdfItem[];
  typeLabel: string;
};

type BuildCreatorLifeEventPdfGroupsOptions = {
  locale: string;
  unknownTypeLabel: string;
};

const normalizeLabel = (value: string): string =>
  value
    .toLowerCase()
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .trim();

const hasAnyTerm = (label: string, terms: string[]): boolean =>
  terms.some((term) => label.includes(term));

// Lower number = earlier in the document. Ordered as a logical life timeline:
// birth → school → studies → work → memberships → awards → exhibitions →
// publications → performances → (anything else) → "other".
const getGroupSortPriority = (label: string): number => {
  const normalizedLabel = normalizeLabel(label);

  if (hasAnyTerm(normalizedLabel, ['szuletett', 'birth', 'born'])) {
    return 10;
  }
  if (hasAnyTerm(normalizedLabel, ['iskola'])) {
    return 20;
  }
  if (hasAnyTerm(normalizedLabel, ['tanulmany', 'kepzes', 'egyetem', 'foiskola'])) {
    return 30;
  }
  if (hasAnyTerm(normalizedLabel, ['munkahely', 'munka', 'allas', 'oktato', 'tanar'])) {
    return 40;
  }
  if (hasAnyTerm(normalizedLabel, ['tagsag', 'tagja', 'szervezet', 'egyesulet', 'akademia'])) {
    return 50;
  }
  if (hasAnyTerm(normalizedLabel, ['dij', 'kituntetes', 'elismeres'])) {
    return 60;
  }
  if (hasAnyTerm(normalizedLabel, ['kiallitas', 'tarlat'])) {
    return 70;
  }
  if (hasAnyTerm(normalizedLabel, ['publikacio', 'kotet', 'konyv', 'megjelent'])) {
    return 80;
  }
  if (hasAnyTerm(normalizedLabel, ['eloadas', 'bemutato', 'koncert', 'program'])) {
    return 90;
  }
  if (hasAnyTerm(normalizedLabel, ['egyeb', 'other'])) {
    return 1000;
  }

  return 800;
};

const getLocationLabel = (event: CreationListItem): string => {
  const locationParts = [event.cim?.city, event.cim?.country]
    .map((part) => normalizePdfText(part))
    .filter(Boolean);

  return locationParts.join(', ');
};

const sortLifeEvents = (events: CreationListItem[]) =>
  events
    .map((event, index) => ({ event, index }))
    .sort((a, b) => {
      const aYear = a.event.labelYear;
      const bYear = b.event.labelYear;
      const aHasYear = typeof aYear === 'number' && aYear !== 1000;
      const bHasYear = typeof bYear === 'number' && bYear !== 1000;

      if (aHasYear !== bHasYear) return aHasYear ? -1 : 1;
      if (aHasYear && bHasYear && aYear !== bYear) return aYear - bYear;

      return a.index - b.index;
    })
    .map(({ event }, sortedIndex) => ({ event, sortedIndex }));

export const buildCreatorLifeEventPdfGroups = (
  events: CreationListItem[],
  { locale, unknownTypeLabel }: BuildCreatorLifeEventPdfGroupsOptions
): CreatorLifeEventPdfGroup[] => {
  const groups = new Map<string, CreatorLifeEventPdfItem[]>();

  for (const { event, sortedIndex } of sortLifeEvents(events)) {
    const typeLabel = normalizePdfText(event.tipusLabel) || unknownTypeLabel;
    const items = groups.get(typeLabel) || [];

    items.push({
      dateLabel: normalizePdfText(event.label),
      key: `${typeLabel}-${event.id ?? event.label ?? 'event'}-${sortedIndex}`,
      location: getLocationLabel(event),
      title: normalizePdfText(event.nev),
    });
    groups.set(typeLabel, items);
  }

  const collator = new Intl.Collator(locale === 'en' ? 'en' : 'hu');

  return Array.from(groups.entries())
    .sort(([a], [b]) => {
      const aPriority = getGroupSortPriority(a);
      const bPriority = getGroupSortPriority(b);

      if (aPriority !== bPriority) return aPriority - bPriority;

      return collator.compare(a, b);
    })
    .map(([typeLabel, groupedEvents]) => ({ typeLabel, events: groupedEvents }));
};
