import Highlighter from 'react-highlight-words';
import { randUser } from '@ngneat/falso';

import { Avatar } from '../avatar';
import { _palette } from '../@styles/theme-provider';
import { userNameToInitials } from '../../utils';
import { countryCodesMap } from '../../consts';
import type { CountryCodes } from '../../consts';
import { ASSETS_URL } from '../../consts/common';

import type { DropdownMenuItem } from './types';

export const areEqualDropdownMenuItems = (item1: DropdownMenuItem, item2: DropdownMenuItem) => {
  return 'value' in item1 && 'value' in item2
    ? item1.value === item2.value
    : item1.name === item2.name;
};

export const getDropdownMenuItemsByCountryCodes = (countryCodes: CountryCodes[]) =>
  countryCodes.map(countryCode => {
    const itemName = countryCode.toString();
    const countryData = countryCode && countryCodesMap[countryCode];
    const countryFlag = countryData?.flag || 'worldwide';
    const countryFlagSrc = `${ASSETS_URL}/flags/${countryFlag}.svg`;

    return {
      name: countryData?.name,
      value: itemName,
      selected: false,
      checkboxProps: {
        icon: <img width={16} src={countryFlagSrc} alt={countryData?.name + ' flag'} />
      }
    } as DropdownMenuItem;
  });

/**
 * @param length Specifies how many items to generate.
 * @param randomDisable Number from 0 to 1, creates randomly disabled users.
 * @returns
 */
export const getMockUsersDropdownMenuItems = (length = 10, randomDisable = 0) => {
  const { specialColors = {} } = _palette;
  return randUser({ length })
    .map(user => {
      const username = user.firstName + ' ' + user.lastName;
      const { color: initialsColor, initials } = userNameToInitials(username, specialColors);
      const icon = Math.random() < 0.25 ? user?.img : undefined;
      return {
        ...user,
        icon,
        initials,
        initialsColor,
        username
      };
    })
    .map(
      user =>
        ({
          id: user.id,
          name: user.username,
          selected: false,
          checkboxProps: {
            disabled: Math.random() < randomDisable,
            icon: (
              <Avatar
                backgroundColor={user.initialsColor}
                customSize={16}
                initials={user.initials}
                src={user.icon}
              />
            )
          }
        } as DropdownMenuItem)
    );
};

export const filterDropdownMenuItemsRecursive = (
  items: DropdownMenuItem[],
  itemCallback: (item: DropdownMenuItem) => boolean
) => {
  return items.map(filterListItemRecursive).filter(Boolean) as DropdownMenuItem[];

  function filterListItemRecursive(listItem: DropdownMenuItem): DropdownMenuItem | false {
    if (listItem.options) {
      return {
        ...listItem,
        options: listItem.options
          ?.map(filterListItemRecursive)
          .filter(Boolean) as DropdownMenuItem[]
      };
    } else {
      return itemCallback(listItem) && listItem;
    }
  }
};

export const highlightDropdownMenuItem = (searchWords: string[]) => (item: DropdownMenuItem) => ({
  ...item,
  textNode: (
    <Highlighter
      autoEscape
      highlightClassName="highlight"
      searchWords={searchWords}
      textToHighlight={item.name.toString()}
    />
  )
});

export const processDropdownMenuItemsRecursive = (
  items: DropdownMenuItem[],
  itemCallback?: (item: DropdownMenuItem) => DropdownMenuItem | void
) => {
  return items.map(processListItemRecursive);

  function processListItemRecursive(listItem: DropdownMenuItem): DropdownMenuItem {
    return listItem.options
      ? {
          ...listItem,
          options: listItem.options?.map(processListItemRecursive)
        }
      : itemCallback?.(listItem) || listItem;
  }
};

export const selectDropdownMenuItemsRecursive = (
  listItems: DropdownMenuItem[],
  values: DropdownMenuItem['value'][],
  toggleMatches?: boolean
) => {
  return processDropdownMenuItemsRecursive(listItems, item => {
    const isMatchedItem: boolean = values?.includes(item.value || item.name);
    if (toggleMatches) {
      return isMatchedItem ? { ...item, selected: !item.selected } : item;
    } else {
      return { ...item, selected: isMatchedItem };
    }
  });
};

export const toggleClickedDropdownMenuItem = (isClickedItem: boolean) => (item: DropdownMenuItem) =>
  isClickedItem ? ({ ...item, selected: !item.selected } as DropdownMenuItem) : item;
