export const SIDEBAR_SORT_KEYS = Object.freeze({
  CREATED_DESC: 'created_at_desc',
  CREATED_ASC: 'created_at_asc',
  ALPHABETICAL_ASC: 'alphabetical_asc',
  ALPHABETICAL_DESC: 'alphabetical_desc',
  UNREAD_COUNT_DESC: 'unread_count_desc',
  UNREAD_COUNT_ASC: 'unread_count_asc',
});

export const SIDEBAR_SORT_SECTIONS = Object.freeze({
  FOLDERS: 'folders',
  TEAMS: 'teams',
  CHANNELS: 'channels',
  LABELS: 'labels',
});

export const SIDEBAR_SORT_OPTIONS_BY_SECTION = Object.freeze({
  [SIDEBAR_SORT_SECTIONS.FOLDERS]: [
    SIDEBAR_SORT_KEYS.CREATED_DESC,
    SIDEBAR_SORT_KEYS.CREATED_ASC,
    SIDEBAR_SORT_KEYS.ALPHABETICAL_ASC,
    SIDEBAR_SORT_KEYS.ALPHABETICAL_DESC,
    SIDEBAR_SORT_KEYS.UNREAD_COUNT_DESC,
    SIDEBAR_SORT_KEYS.UNREAD_COUNT_ASC,
  ],
  [SIDEBAR_SORT_SECTIONS.TEAMS]: [
    SIDEBAR_SORT_KEYS.CREATED_DESC,
    SIDEBAR_SORT_KEYS.CREATED_ASC,
    SIDEBAR_SORT_KEYS.ALPHABETICAL_ASC,
    SIDEBAR_SORT_KEYS.ALPHABETICAL_DESC,
    SIDEBAR_SORT_KEYS.UNREAD_COUNT_DESC,
    SIDEBAR_SORT_KEYS.UNREAD_COUNT_ASC,
  ],
  [SIDEBAR_SORT_SECTIONS.CHANNELS]: [
    SIDEBAR_SORT_KEYS.CREATED_DESC,
    SIDEBAR_SORT_KEYS.CREATED_ASC,
    SIDEBAR_SORT_KEYS.ALPHABETICAL_ASC,
    SIDEBAR_SORT_KEYS.ALPHABETICAL_DESC,
    SIDEBAR_SORT_KEYS.UNREAD_COUNT_DESC,
    SIDEBAR_SORT_KEYS.UNREAD_COUNT_ASC,
  ],
  [SIDEBAR_SORT_SECTIONS.LABELS]: [
    SIDEBAR_SORT_KEYS.CREATED_DESC,
    SIDEBAR_SORT_KEYS.CREATED_ASC,
    SIDEBAR_SORT_KEYS.ALPHABETICAL_ASC,
    SIDEBAR_SORT_KEYS.ALPHABETICAL_DESC,
    SIDEBAR_SORT_KEYS.UNREAD_COUNT_DESC,
    SIDEBAR_SORT_KEYS.UNREAD_COUNT_ASC,
  ],
});

const UNREAD_COUNT_SORT_OPTIONS = [
  SIDEBAR_SORT_KEYS.UNREAD_COUNT_DESC,
  SIDEBAR_SORT_KEYS.UNREAD_COUNT_ASC,
];

export const DEFAULT_SIDEBAR_SORT_PREFERENCES = Object.freeze({
  [SIDEBAR_SORT_SECTIONS.FOLDERS]: SIDEBAR_SORT_KEYS.CREATED_DESC,
  [SIDEBAR_SORT_SECTIONS.TEAMS]: SIDEBAR_SORT_KEYS.UNREAD_COUNT_DESC,
  [SIDEBAR_SORT_SECTIONS.CHANNELS]: SIDEBAR_SORT_KEYS.UNREAD_COUNT_DESC,
  [SIDEBAR_SORT_SECTIONS.LABELS]: SIDEBAR_SORT_KEYS.UNREAD_COUNT_DESC,
});

export const isValidSidebarSort = (section, sortBy) => {
  return SIDEBAR_SORT_OPTIONS_BY_SECTION[section]?.includes(sortBy);
};

const isUnreadCountSort = sortBy => UNREAD_COUNT_SORT_OPTIONS.includes(sortBy);

export const getSidebarSortOptions = (
  section,
  { hasUnreadCounts = true } = {}
) => {
  const options = SIDEBAR_SORT_OPTIONS_BY_SECTION[section] || [];

  if (hasUnreadCounts) return options;

  return options.filter(option => !isUnreadCountSort(option));
};

export const resolveSidebarSort = (
  section,
  sortBy,
  { hasUnreadCounts = true } = {}
) => {
  const options = getSidebarSortOptions(section, { hasUnreadCounts });

  if (options.includes(sortBy)) return sortBy;
  if (!hasUnreadCounts && isUnreadCountSort(sortBy)) {
    return SIDEBAR_SORT_KEYS.ALPHABETICAL_ASC;
  }

  return options[0] || SIDEBAR_SORT_KEYS.ALPHABETICAL_ASC;
};

export const normalizeSidebarSortPreferences = (preferences = {}) => {
  const savedPreferences = preferences || {};

  return Object.keys(DEFAULT_SIDEBAR_SORT_PREFERENCES).reduce(
    (result, section) => {
      const sortBy = savedPreferences[section];
      result[section] = isValidSidebarSort(section, sortBy)
        ? sortBy
        : DEFAULT_SIDEBAR_SORT_PREFERENCES[section];
      return result;
    },
    {}
  );
};

const normalizeUnreadCount = count => {
  const unreadCount = Number(count);
  return Number.isFinite(unreadCount) && unreadCount > 0 ? unreadCount : 0;
};

const getCreatedValue = item => {
  const createdAt = item.created_at || item.createdAt;

  if (typeof createdAt === 'number') return createdAt;

  if (createdAt) {
    const timestamp = Date.parse(createdAt);
    if (Number.isFinite(timestamp)) return timestamp;
  }

  const id = Number(item.id);
  return Number.isFinite(id) ? id : 0;
};

const getLabelValue = (item, labelKey) => {
  return String(labelKey(item) || '');
};

const compareAlphabetically = (a, b, labelKey) => {
  return getLabelValue(a, labelKey).localeCompare(
    getLabelValue(b, labelKey),
    undefined,
    {
      sensitivity: 'base',
    }
  );
};

export const sortSidebarItems = (
  items,
  { sortBy, labelKey, unreadCountKey = () => 0 }
) => {
  return (items || []).slice().sort((a, b) => {
    if (sortBy === SIDEBAR_SORT_KEYS.CREATED_DESC) {
      const createdDiff = getCreatedValue(b) - getCreatedValue(a);
      if (createdDiff !== 0) return createdDiff;
      return compareAlphabetically(a, b, labelKey);
    }

    if (sortBy === SIDEBAR_SORT_KEYS.CREATED_ASC) {
      const createdDiff = getCreatedValue(a) - getCreatedValue(b);
      if (createdDiff !== 0) return createdDiff;
      return compareAlphabetically(a, b, labelKey);
    }

    if (sortBy === SIDEBAR_SORT_KEYS.ALPHABETICAL_DESC) {
      return compareAlphabetically(b, a, labelKey);
    }

    if (sortBy === SIDEBAR_SORT_KEYS.UNREAD_COUNT_DESC) {
      const unreadCountDiff =
        normalizeUnreadCount(unreadCountKey(b)) -
        normalizeUnreadCount(unreadCountKey(a));

      if (unreadCountDiff !== 0) return unreadCountDiff;
    }

    if (sortBy === SIDEBAR_SORT_KEYS.UNREAD_COUNT_ASC) {
      const unreadCountDiff =
        normalizeUnreadCount(unreadCountKey(a)) -
        normalizeUnreadCount(unreadCountKey(b));

      if (unreadCountDiff !== 0) return unreadCountDiff;
    }

    return compareAlphabetically(a, b, labelKey);
  });
};
