/**
 * MultiSelect component - Multi-select dropdown with checkboxes.
 *
 * @package GetMD
 * @since   1.0.0
 */

import * as React from 'react';
import { Check, ChevronsUpDown, X } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from './button';
import { Popover, PopoverContent, PopoverTrigger } from './popover';
import { Checkbox } from './checkbox';

export interface MultiSelectOption<T = string> {
  value: T;
  label: string;
}

interface MultiSelectProps<T = string> {
  options: MultiSelectOption<T>[];
  selected: T[];
  onChange: (values: T[]) => void;
  placeholder?: string;
  disabled?: boolean;
  className?: string;
}

/**
 * Render a controlled multi-select dropdown with checkboxes allowing multiple options to be selected.
 *
 * @param options - Array of option objects with `value` and `label` to display in the dropdown.
 * @param selected - Current array of selected option values (controlled).
 * @param onChange - Callback invoked with the updated array of selected values whenever the selection changes or is cleared.
 * @param placeholder - Text to display in the trigger when no options are selected. Defaults to "Select items".
 * @param disabled - When true, disables the trigger button and prevents opening the dropdown. Defaults to false.
 * @param className - Optional additional class name(s) applied to the trigger button.
 * @returns A JSX element representing the MultiSelect component.
 */
export function MultiSelect<T = string>({
  options,
  selected,
  onChange,
  placeholder,
  disabled = false,
  className,
}: MultiSelectProps<T>) {
  const { i18n } = window.summixGetmdData || {};
  const [open, setOpen] = React.useState(false);
  const defaultPlaceholder = i18n?.choose || 'Choose...';

  // Memoize handlers to prevent recreation on every render
  const handleSelect = React.useCallback(
    (value: T) => {
      const newSelected = selected.includes(value)
        ? selected.filter((item) => item !== value)
        : [...selected, value];
      onChange(newSelected);
    },
    [selected, onChange]
  );

  const handleClear = React.useCallback(
    (e: React.MouseEvent) => {
      e.stopPropagation();
      onChange([]);
    },
    [onChange]
  );

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          variant="outline"
          role="combobox"
          aria-expanded={open}
          className={cn(
            'smx-w-full smx-justify-between smx-font-normal',
            !selected.length && 'smx-text-muted-foreground',
            className
          )}
          disabled={disabled}
        >
          <span className="smx-truncate">
            {selected.length > 0
              ? (i18n?.selected?.replace('%d', String(selected.length)) || `${selected.length} selected`)
              : (placeholder || defaultPlaceholder)}
          </span>
          <div className="smx-flex smx-items-center smx-gap-1">
            {selected.length > 0 && (
              <X
                className="smx-h-4 smx-w-4 smx-shrink-0 smx-opacity-50 hover:smx-opacity-100"
                onClick={handleClear}
              />
            )}
            <ChevronsUpDown className="smx-h-4 smx-w-4 smx-shrink-0 smx-opacity-50" />
          </div>
        </Button>
      </PopoverTrigger>
      <PopoverContent className="smx-w-full smx-p-0" align="start">
        <div className="smx-max-h-64 smx-overflow-auto smx-p-1">
          {options.map((option) => {
            const isSelected = selected.includes(option.value);
            return (
              <div
                key={String(option.value)}
                className={cn(
                  'smx-flex smx-items-center smx-gap-2 smx-rounded-sm smx-px-2 smx-py-1.5 smx-text-sm smx-cursor-pointer hover:smx-bg-accent hover:smx-text-accent-foreground',
                  isSelected && 'smx-bg-accent'
                )}
                onClick={() => handleSelect(option.value)}
                role="option"
                aria-selected={isSelected}
              >
                <Checkbox
                  checked={isSelected}
                  tabIndex={-1}
                  className="smx-pointer-events-none"
                />
                <span className="smx-flex-1">{option.label}</span>
                {isSelected && (
                  <Check className="smx-h-4 smx-w-4 smx-shrink-0" />
                )}
              </div>
            );
          })}
        </div>
      </PopoverContent>
    </Popover>
  );
}