import { type RefObject, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { normalizeVariables } from '../../utils/variableSerialization';
import Menu from '@design-system/Menu';
import MenuItem from '@design-system/Menu/components/MenuItem';
import { Box, InputAdornment, InputBase, Stack, useTheme } from '@mui/material';
import {
  IconChevronLeft,
  IconChevronRight,
  IconSearch,
} from '@tabler/icons-react';

import { type VariableNode, type VariableNodeInput } from './types';

type InsertVariableMenuProps = {
  anchorRef: RefObject<HTMLButtonElement>;
  open: boolean;
  onClose: () => void;
  onSelect: (token: string, label: string) => void;
  variables: VariableNodeInput[];
};

const collectLeaves = (
  nodes: VariableNode[],
  parentKey?: string,
  parentLabel?: string,
): Array<{ token: string; label: string; displayLabel: string }> => {
  const results: Array<{ token: string; label: string; displayLabel: string }> =
    [];

  for (const node of nodes) {
    const currentKey = parentKey ? `${parentKey}.${node.key}` : node.key;
    const currentLabel = parentLabel
      ? `${parentLabel} - ${node.label}`
      : node.label;

    if (node.children.length === 0) {
      results.push({
        token: currentKey,
        label: currentLabel,
        displayLabel: node.label,
      });
    } else {
      results.push(...collectLeaves(node.children, currentKey, currentLabel));
    }
  }

  return results;
};

const InsertVariableMenu = ({
  anchorRef,
  open,
  onClose,
  onSelect,
  variables,
}: InsertVariableMenuProps) => {
  const theme = useTheme();
  const { t } = useTranslation('material_hu_only');
  const [search, setSearch] = useState('');
  const [selectedCategory, setSelectedCategory] = useState<VariableNode | null>(
    null,
  );

  const normalizedVariables = useMemo(
    () => normalizeVariables(variables),
    [variables],
  );
  const query = search.toLowerCase().trim();

  const handleClose = () => {
    onClose();
    setSearch('');
    setSelectedCategory(null);
  };

  const handleSelect = (token: string, label: string) => {
    onSelect(token, label);
    setSearch('');
    setSelectedCategory(null);
  };

  const handleBack = () => {
    setSelectedCategory(null);
    setSearch('');
  };

  const categoryLeaves = useMemo(
    () =>
      selectedCategory
        ? collectLeaves(
            selectedCategory.children,
            selectedCategory.key,
            selectedCategory.label,
          )
        : [],
    [selectedCategory],
  );

  const searchResults = query
    ? categoryLeaves.filter(leaf => leaf.label.toLowerCase().includes(query))
    : [];

  const level2Header = selectedCategory ? (
    <Stack>
      <MenuItem
        onClick={handleBack}
        sx={{
          gap: 1,
          color: theme.palette.new.text.neutral.default,
          typography: 'body2',
          fontWeight: 600,
        }}
      >
        <IconChevronLeft size={16} />
        <span>{selectedCategory.label}</span>
      </MenuItem>
      <InputBase
        autoFocus
        value={search}
        onChange={e => setSearch(e.target.value)}
        placeholder={t(
          'top_bar_rich_text_editor.insert_variable_search_placeholder',
        )}
        startAdornment={
          <InputAdornment position="start">
            <IconSearch
              size={16}
              color={theme.palette.new.text.neutral.lighter}
            />
          </InputAdornment>
        }
        sx={{
          px: 2,
          py: 1,
          typography: 'body2',
          color: theme.palette.new.text.neutral.default,
          width: 240,
        }}
      />
    </Stack>
  ) : undefined;

  if (query && selectedCategory) {
    return (
      <Menu
        open={open}
        anchorEl={anchorRef.current}
        onClose={handleClose}
        fixedDimensions
        position="left"
        header={level2Header}
        sx={{ '& .MuiList-root': { p: 0 } }}
      >
        {searchResults.length === 0 ? (
          <Stack
            sx={{
              px: 2,
              py: 1.5,
              typography: 'body2',
              color: theme.palette.new.text.neutral.lighter,
            }}
          >
            {t('top_bar_rich_text_editor.insert_variable_no_results')}
          </Stack>
        ) : (
          searchResults.map(leaf => (
            <MenuItem
              key={leaf.token}
              onClick={() => handleSelect(leaf.token, leaf.label)}
              sx={{
                px: 2,
                gap: 1,
                color: theme.palette.new.text.neutral.default,
                typography: 'body2',
              }}
            >
              <span>{leaf.displayLabel}</span>
            </MenuItem>
          ))
        )}
      </Menu>
    );
  }

  if (selectedCategory) {
    return (
      <Menu
        open={open}
        anchorEl={anchorRef.current}
        onClose={handleClose}
        fixedDimensions
        position="left"
        header={level2Header}
        sx={{ '& .MuiList-root': { p: 0 } }}
      >
        {categoryLeaves.map(leaf => (
          <MenuItem
            key={leaf.token}
            onClick={() => handleSelect(leaf.token, leaf.label)}
            sx={{
              px: 2,
              gap: 1,
              color: theme.palette.new.text.neutral.default,
              typography: 'body2',
            }}
          >
            <span>{leaf.displayLabel}</span>
          </MenuItem>
        ))}
      </Menu>
    );
  }

  return (
    <Menu
      open={open}
      anchorEl={anchorRef.current}
      onClose={handleClose}
      fixedDimensions
      position="left"
      sx={{ '& .MuiList-root': { p: 0 } }}
    >
      {normalizedVariables.map(category => (
        <MenuItem
          key={category.key}
          onClick={() => setSelectedCategory(category)}
          sx={{
            px: 2,
            gap: 1,
            justifyContent: 'space-between',
            color: theme.palette.new.text.neutral.default,
            typography: 'body2',
          }}
        >
          <span>{category.label}</span>
          <Box
            component="span"
            sx={{ display: 'inline-flex', flexShrink: 0 }}
          >
            <IconChevronRight size={16} />
          </Box>
        </MenuItem>
      ))}
    </Menu>
  );
};

export default InsertVariableMenu;
