'use client';

import { useMemo, useState } from 'react';
import { Check, ChevronDown } from 'lucide-react';

import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@/components/ui/popover';
import { cn } from '@/lib/utils';

export interface MultiSelectOption {
  value: string;
  label: string;
  disabled?: boolean;
}

interface MultiSelectPopoverProps {
  label: string;
  icon?: React.ReactNode;
  options: MultiSelectOption[];
  values: string[];
  onValuesChange: (values: string[]) => void;
  searchPlaceholder?: string;
  emptyMessage?: string;
  emptySelectionLabel?: string;
  align?: 'start' | 'center' | 'end';
}

function checkboxClass(checked: boolean) {
  return cn(
    'flex size-4 shrink-0 items-center justify-center rounded-lg border',
    checked && 'border-primary bg-primary text-primary-foreground',
  );
}

export function MultiSelectPopover({
  label,
  icon,
  options,
  values,
  onValuesChange,
  searchPlaceholder = 'Search',
  emptyMessage = 'No options found.',
  emptySelectionLabel,
  align = 'end',
}: MultiSelectPopoverProps) {
  const [search, setSearch] = useState('');
  const selectedValues = useMemo(() => new Set(values), [values]);
  const selectableOptions = options.filter((option) => !option.disabled);
  const areAllSelected =
    selectableOptions.length > 0 &&
    selectableOptions.every((option) => selectedValues.has(option.value));
  const filteredOptions = useMemo(() => {
    const term = search.trim().toLowerCase();
    if (!term) return options;
    return options.filter((option) =>
      option.label.toLowerCase().includes(term),
    );
  }, [options, search]);

  const toggleValue = (value: string) => {
    const nextValues = new Set(values);
    if (nextValues.has(value)) {
      nextValues.delete(value);
    } else {
      nextValues.add(value);
    }
    onValuesChange(Array.from(nextValues));
  };

  const toggleAll = () => {
    const nextValues = new Set(values);

    selectableOptions.forEach((option) => {
      if (areAllSelected) {
        nextValues.delete(option.value);
      } else {
        nextValues.add(option.value);
      }
    });

    onValuesChange(Array.from(nextValues));
  };

  return (
    <Popover>
      <PopoverTrigger asChild>
        <Button
          type="button"
          variant="outline"
          size="sm"
          className="shadow-none"
        >
          {icon}
          {label}
          <Badge variant="secondary">
            {values.length === 0 && emptySelectionLabel
              ? emptySelectionLabel
              : values.length}
          </Badge>
          <ChevronDown />
        </Button>
      </PopoverTrigger>
      <PopoverContent align={align} className="w-60 p-0 shadow-none">
        <div className="flex items-center gap-2 border-b p-3">
          <button
            type="button"
            onClick={toggleAll}
            aria-label={`Toggle all ${label}`}
            className="shrink-0 cursor-pointer rounded-lg p-0.5 hover:bg-muted"
          >
            <span className={checkboxClass(areAllSelected)}>
              {areAllSelected ? <Check className="size-3" /> : null}
            </span>
          </button>
          <Input
            value={search}
            onChange={(event) => setSearch(event.target.value)}
            placeholder={searchPlaceholder}
            className="flex-1"
          />
        </div>

        <div className="max-h-72 overflow-y-auto p-2">
          {filteredOptions.length ? (
            filteredOptions.map((option) => {
              const checked = selectedValues.has(option.value);

              return (
                <div
                  key={option.value}
                  className="flex items-center gap-2 rounded-lg px-2 py-1.5 hover:bg-muted"
                >
                  <button
                    type="button"
                    disabled={option.disabled}
                    onClick={() => toggleValue(option.value)}
                    className={cn(
                      'flex min-w-0 flex-1 cursor-pointer items-center gap-2 text-left',
                      option.disabled && 'cursor-not-allowed opacity-60',
                    )}
                  >
                    <span className={checkboxClass(checked)}>
                      {checked ? <Check className="size-3" /> : null}
                    </span>
                    <span className="truncate">{option.label}</span>
                  </button>
                </div>
              );
            })
          ) : (
            <div className="px-2 py-6 text-center text-muted-foreground">
              {emptyMessage}
            </div>
          )}
        </div>
      </PopoverContent>
    </Popover>
  );
}
