import data from '@emoji-mart/data';

export type UnicodeEmojiCategoryId =
  | 'people'
  | 'nature'
  | 'foods'
  | 'activity'
  | 'places'
  | 'objects'
  | 'symbols'
  | 'flags';

export interface UnicodeEmojiItem {
  id: string;
  name: string;
  keywords: string[];
  skins: string[];
}

export interface UnicodeEmojiCategory {
  id: UnicodeEmojiCategoryId;
  /** Representative emoji for the sidebar icon */
  icon: string;
  emojis: UnicodeEmojiItem[];
}

type EmojiMartSkin = { native: string; unified: string };
type EmojiMartEmoji = {
  id: string;
  name: string;
  keywords?: string[];
  skins: EmojiMartSkin[];
};

type EmojiMartData = {
  categories: Array<{ id: string; emojis: string[] }>;
  emojis: Record<string, EmojiMartEmoji>;
};

const mart = data as unknown as EmojiMartData;

const CATEGORY_ICONS: Record<UnicodeEmojiCategoryId, string> = {
  people: '😀',
  nature: '🐻',
  foods: '🍔',
  activity: '⚽',
  places: '✈️',
  objects: '💡',
  symbols: '❤️',
  flags: '🏳️'
};

const CATEGORY_ORDER: UnicodeEmojiCategoryId[] = [
  'people',
  'nature',
  'foods',
  'activity',
  'places',
  'objects',
  'symbols',
  'flags'
];

function toItem(emoji: EmojiMartEmoji): UnicodeEmojiItem {
  return {
    id: emoji.id,
    name: emoji.name,
    keywords: emoji.keywords ?? [],
    skins: emoji.skins.map((skin) => skin.native)
  };
}

export const UNICODE_EMOJI_CATEGORIES: UnicodeEmojiCategory[] = CATEGORY_ORDER.map((id) => {
  const category = mart.categories.find((entry) => entry.id === id);
  const emojis = (category?.emojis ?? [])
    .map((emojiId) => mart.emojis[emojiId])
    .filter((emoji): emoji is EmojiMartEmoji => Boolean(emoji))
    .map(toItem);
  return {
    id,
    icon: CATEGORY_ICONS[id],
    emojis
  };
});

export const ALL_UNICODE_EMOJIS: UnicodeEmojiItem[] = UNICODE_EMOJI_CATEGORIES.flatMap(
  (category) => category.emojis
);

export function pickEmojiNative(emoji: UnicodeEmojiItem, skinToneIndex: number): string {
  if (emoji.skins.length <= 1) {
    return emoji.skins[0] ?? '';
  }
  const index = Math.min(Math.max(skinToneIndex, 0), emoji.skins.length - 1);
  return emoji.skins[index] ?? emoji.skins[0] ?? '';
}

export function searchUnicodeEmojis(query: string, skinToneIndex: number): Array<{
  emoji: UnicodeEmojiItem;
  native: string;
  categoryId: UnicodeEmojiCategoryId;
}> {
  const needle = query.trim().toLocaleLowerCase();
  if (!needle) {
    return [];
  }

  const results: Array<{
    emoji: UnicodeEmojiItem;
    native: string;
    categoryId: UnicodeEmojiCategoryId;
  }> = [];

  for (const category of UNICODE_EMOJI_CATEGORIES) {
    for (const emoji of category.emojis) {
      const haystack = [emoji.id, emoji.name, ...emoji.keywords].join(' ').toLocaleLowerCase();
      if (!haystack.includes(needle) && !emoji.skins.some((skin) => skin.includes(needle))) {
        continue;
      }
      results.push({
        emoji,
        native: pickEmojiNative(emoji, skinToneIndex),
        categoryId: category.id
      });
    }
  }

  return results;
}

export const SKIN_TONE_PREVIEW = ['👏', '👏🏻', '👏🏼', '👏🏽', '👏🏾', '👏🏿'] as const;
