import {
  MAX_CATEGORY_CHIP_NAME,
  MAX_VISIBLE_CATEGORY_CHIPS,
} from '../constants';
import { type ActiveCategory } from '../types';

export type ResolveChipLayoutParams = {
  activeCategories: ActiveCategory[] | undefined;
  selectedCategoryId: number | null;
  /** Custom chip order from drawer; empty = first 4 active categories from API */
  chipOrderIds: number[];
};

/**
 * Puts the selected category in chip slot 1 and keeps up to the previous three.
 * The former fourth chip moves to the drawer list.
 */
export const promoteChipOrder = (
  selectedCategoryId: number,
  currentChipOrderIds: number[],
) => [
  selectedCategoryId,
  ...currentChipOrderIds.slice(0, MAX_VISIBLE_CATEGORY_CHIPS - 1),
];

const mapIdsToChipLayout = (
  categories: ActiveCategory[],
  chipIds: number[],
) => {
  const categoriesById = new Map(
    categories.map(category => [category.id, category]),
  );

  const visibleCategories = chipIds
    .map(id => categoriesById.get(id))
    .filter((category): category is ActiveCategory => category != null)
    .slice(0, MAX_VISIBLE_CATEGORY_CHIPS);

  const visibleIds = new Set(visibleCategories.map(({ id }) => id));
  const hiddenCategories = categories.filter(
    category => !visibleIds.has(category.id),
  );

  return { visibleCategories, hiddenCategories };
};

/**
 * Resolves visible chip categories and the "See all" drawer list from URL
 * selection, optional custom chip order, and active categories from the API.
 */
export const resolveCategoryChipLayout = ({
  activeCategories,
  selectedCategoryId,
  chipOrderIds,
}: ResolveChipLayoutParams) => {
  const categories = activeCategories ?? [];

  if (!categories.length) {
    return { visibleCategories: [], hiddenCategories: [] };
  }

  const defaultChipIds = categories
    .slice(0, MAX_VISIBLE_CATEGORY_CHIPS)
    .map(({ id }) => id);

  const baseChipIds = chipOrderIds.length > 0 ? chipOrderIds : defaultChipIds;

  const effectiveChipIds =
    selectedCategoryId != null && !baseChipIds.includes(selectedCategoryId)
      ? promoteChipOrder(selectedCategoryId, baseChipIds)
      : baseChipIds;

  return mapIdsToChipLayout(categories, effectiveChipIds);
};

/** Truncates a category name for chip display, appending "..." when over the limit. */
export const truncateCategoryName = (name: string) =>
  name.length > MAX_CATEGORY_CHIP_NAME
    ? `${name.slice(0, MAX_CATEGORY_CHIP_NAME).trimEnd()}...`
    : name;
