"use client"

import { Check, ChevronsUpDown } from "lucide-react"

import { Button } from "@/components/ui/button"
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command"
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover"
import { cn } from "@/lib/utils"

export interface MultiSelectOption {
  label: string
  value: string
}

interface MultiSelectProps {
  options: MultiSelectOption[]
  value: string[]
  onValueChange: (value: string[]) => void
  placeholder: string
  searchPlaceholder: string
  emptyMessage: string
  suggestionsLabel?: string
  suggestionLimit?: number
  invalid?: boolean
  dir?: "ltr" | "rtl"
}

export function MultiSelect({
  options,
  value,
  onValueChange,
  placeholder,
  searchPlaceholder,
  emptyMessage,
  suggestionsLabel,
  suggestionLimit = 6,
  invalid = false,
  dir = "ltr",
}: MultiSelectProps) {
  const selectedOptions = options.filter((option) => value.includes(option.value))
  const suggestedOptions = options.slice(0, suggestionLimit)

  const toggleOption = (optionValue: string) => {
    onValueChange(
      value.includes(optionValue)
        ? value.filter((item) => item !== optionValue)
        : [...value, optionValue]
    )
  }

  return (
    <div className="space-y-2" dir={dir}>
      <Popover>
        <PopoverTrigger asChild>
          <Button
            type="button"
            variant="outline"
            role="combobox"
            aria-invalid={invalid}
            className={cn(
              "h-12 w-full justify-between rounded-xl border-border bg-background px-4 font-normal",
              selectedOptions.length === 0 && "text-muted-foreground"
            )}
          >
            <span className="truncate">
              {selectedOptions.length > 0
                ? selectedOptions.map((option) => option.label).join(", ")
                : placeholder}
            </span>
            <ChevronsUpDown className="size-4 shrink-0 text-muted-foreground" />
          </Button>
        </PopoverTrigger>
        <PopoverContent
          align={dir === "rtl" ? "end" : "start"}
          className="w-[--radix-popover-trigger-width] p-0"
        >
          <Command>
            <CommandInput placeholder={searchPlaceholder} />
            <CommandList>
              <CommandEmpty>{emptyMessage}</CommandEmpty>
              <CommandGroup>
                {options.map((option) => {
                  const selected = value.includes(option.value)

                  return (
                    <CommandItem
                      key={option.value}
                      value={`${option.label} ${option.value}`}
                      onSelect={() => toggleOption(option.value)}
                      className="min-h-10"
                    >
                      <span
                        className={cn(
                          "flex size-4 items-center justify-center rounded-sm border border-primary",
                          selected
                            ? "bg-primary text-primary-foreground"
                            : "opacity-50 [&_svg]:invisible"
                        )}
                      >
                        <Check className="size-3" />
                      </span>
                      <span>{option.label}</span>
                    </CommandItem>
                  )
                })}
              </CommandGroup>
            </CommandList>
          </Command>
        </PopoverContent>
      </Popover>

      {suggestedOptions.length > 0 && (
        <div className="flex flex-wrap items-center gap-2">
          {suggestionsLabel && (
            <span className="text-sm text-muted-foreground">{suggestionsLabel}</span>
          )}
          {suggestedOptions.map((option) => {
            const selected = value.includes(option.value)

            return (
              <Button
                key={option.value}
                type="button"
                variant={selected ? "toggle-active" : "toggle"}
                size="sm"
                aria-pressed={selected}
                onClick={() => toggleOption(option.value)}
                className="rounded-full"
              >
                {option.label}
              </Button>
            )
          })}
        </div>
      )}
    </div>
  )
}
