import { useState, type CSSProperties, useMemo } from "react";
import Icon from "./icon";
import styles from "./SelectRecipeMenu.module.css";
import Tooltip from "./Tooltip";
import SimpleBar from "simplebar-react";

// Utility type definitions
export type Category<T> = {
  name: string;
  icon: string;
  subGroup: SubGroup<T>[];
};
export type SubGroup<T> = {
  name: string;
  order?: string;
  children: Array<T>;
};
/**
 * Represents a single selectable item.
 * @property {string} name – Display name of the item.
 * @property {string} icon – Identifier of the icon to render.
 */
export type MenuItem = { name: string; icon: string };

interface SubGroupProps {
  subgroup: SubGroup<MenuItem>;
  selectedItem: string;
  onSelectItem: (name: string) => void;
}

// Constants
const ITEM_PER_ROW = 10;

/**
 * Filters a {@link Category} based on a search string.
 * Only sub‑groups and items that contain *all* search terms are
 * retained. The function returns a **new** category object; the
 * original data is never mutated.
 *
 * @param {Category<MenuItem>} category - Original category to filter.
 * @param {string} search - User’s search query (space separated).
 * @returns {Category<MenuItem>} - A filtered copy of the category.
 */
function filterCategory(category: Category<MenuItem>, search: string): Category<MenuItem> {
  const searchKeys = search.toLowerCase().split(" ");

  // Filter the children inside a single sub‑group
  function filterSubgroupChildren(subgroup: SubGroup<MenuItem>): SubGroup<MenuItem> {
    const children = subgroup.children.filter((item) => searchKeys.every((k) => item.name.includes(k)));
    return {
      ...subgroup,
      children,
    };
  }
  return {
    ...category,
    subGroup: category.subGroup.map(filterSubgroupChildren).filter((s) => s.children.length > 0),
  };
}

/**
 * Renders a single row of icons representing a sub‑group’s items.
 *
 * Empty slots are rendered to keep the grid layout intact when the
 * number of items is not a multiple of {@link ITEM_PER_ROW}.
 *
 * @component
 * @param {SubGroupProps} props
 */
function SubGroupRow({ subgroup, selectedItem, onSelectItem }: SubGroupProps) {
  const emptySlotsCounts = useMemo(() => {
    const lastRowSlots = subgroup.children.length % ITEM_PER_ROW;
    return lastRowSlots > 0 ? ITEM_PER_ROW - lastRowSlots : 0;
  }, [subgroup]);
  return (
    <div className={styles.selectMenuContentRow}>
      {subgroup.children.map((o) => (
        <Tooltip title={o.name} key={o.name}>
          <div
            className={`${styles.selectMenuIcon} ${o.name === selectedItem ? styles.active : ""}`}
            onClick={() => onSelectItem(o.name)}
          >
            <Icon iconName={o.icon} size={30} />
          </div>
        </Tooltip>
      ))}
      {Array(emptySlotsCounts)
        .fill(0)
        .map((_, i) => (
          <div className={styles.selectMenuSlot} key={i}>
            <div className={styles.selectMenuSlotEmpty} />
          </div>
        ))}
    </div>
  );
}

/**
 * The main dropdown menu component. It renders:
 *   - A header with optional title and search bar
 *   - Category icons for switching between categories
 *   - A scrollable list of {@link SubGroupRow}s for the current
 *     category
 *
 * The component accepts an optional {@link onSelectItem} callback;
 * if omitted it simply updates internal state and returns the name
 * of the selected item via the `selectItem` state hook.
 *
 * @component
 * @param {SelectMenuProps} props
 */
type SelectMenuProps = {
  categories: Category<MenuItem>[];
  className?: string;
  title?: string;
  style?: CSSProperties;
  onClose?: () => void;
  onSelectItem?: (itemName: string) => void;
};
function SelectMenu({ style, className, title, categories, onClose, onSelectItem }: SelectMenuProps) {
  const [category, setCategory] = useState(categories[0].name);
  const [item, selectItem] = useState("");
  const [showSearch, setShowSearch] = useState(false);
  const [search, setSearch] = useState("");

  const activeCategory = useMemo(() => categories.find((r) => r.name == category), [category, categories]);
  const activeOnSelect = useMemo(() => (onSelectItem ? onSelectItem : selectItem), [onSelectItem, selectItem]);
  // Apply filtering only if a search is active
  const filteredContent = useMemo(
    () => (search && activeCategory && showSearch ? filterCategory(activeCategory, search) : activeCategory),
    [activeCategory, search, showSearch]
  );
  const rootClassName = `${styles.selectMenu} ${className ?? ""}`;
  console.log(styles);
  return (
    <div style={style} className={rootClassName}>
      {/* Header */}
      <div className={styles.selectMenuHeader}>
        <div className={styles.selectMenuHeaderTitle}>{title ?? "Title"}</div>
        <div className={styles.selectMenuHeaderSpacer} />
        <div className={styles.selectMenuHeaderAction}>
          {showSearch && <input type="search" onChange={(evt) => setSearch(evt.target.value)} value={search} />}
          <button className={`panel-button ${showSearch ? "active" : ""}`} onClick={() => setShowSearch(!showSearch)}>
            <img src="/assets/search.png" alt="Search" />
          </button>
          <button className="panel-button" onClick={onClose}>
            <img src="/assets/close.png" alt="Close" />
          </button>
        </div>
      </div>
      {/* Category icons */}
      <div className={styles.selectMenuGroup}>
        {categories.map((g) => (
          <div
            key={g.name}
            className={`${styles.selectMenuGroupIcon} ${g.name === category ? styles.active : ""}`}
            onClick={() => setCategory(g.name)}
          >
            <Icon iconName={g.icon} size={62} />
          </div>
        ))}
      </div>
      {/* Scrollable content */}
      <div className={styles.selectMenuContent}>
        <SimpleBar style={{ maxHeight: 300 }}>
          {filteredContent?.subGroup.map((subgroup) => (
            <SubGroupRow key={subgroup.name} subgroup={subgroup} selectedItem={item} onSelectItem={activeOnSelect} />
          ))}
        </SimpleBar>
      </div>
    </div>
  );
}
export default SelectMenu;
