"use client";

import * as React from "react";
import { Combobox } from "@base-ui/react/combobox";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { CheckIcon, ChevronDownIcon, SearchIcon } from "lucide-react";
import { cn } from "@/lib/utils";

export interface SelectAppOption {
  value: string;
  label: string;
  icon?: React.ReactNode;
  disabled?: boolean;
}

export interface SelectAppProps {
  value: string;
  onValueChange: (value: string) => void;
  options: SelectAppOption[];
  placeholder?: string;
  /** Aktifkan search input di dalam dropdown */
  searchable?: boolean;
  searchPlaceholder?: string;
  disabled?: boolean;
  invalid?: boolean;
  className?: string;
}

export const SelectApp = React.forwardRef<HTMLButtonElement, SelectAppProps>(
  function SelectApp(
    {
      value,
      onValueChange,
      options,
      placeholder = "Pilih...",
      searchable = false,
      searchPlaceholder = "Cari...",
      disabled,
      invalid,
      className,
    },
    ref
  ) {
    if (searchable) {
      return (
        <SearchableSelect
          ref={ref}
          value={value}
          onValueChange={onValueChange}
          options={options}
          placeholder={placeholder}
          searchPlaceholder={searchPlaceholder}
          disabled={disabled}
          invalid={invalid}
          className={className}
        />
      );
    }

    return (
      <PlainSelect
        ref={ref}
        value={value}
        onValueChange={onValueChange}
        options={options}
        placeholder={placeholder}
        disabled={disabled}
        invalid={invalid}
        className={className}
      />
    );
  }
);

/* ─────────────────────────────────────────
   Plain Select (Base UI Select)
───────────────────────────────────────── */
const PlainSelect = React.forwardRef<
  HTMLButtonElement,
  Omit<SelectAppProps, "searchable" | "searchPlaceholder">
>(function PlainSelect(
  { value, onValueChange, options, placeholder, disabled, invalid, className },
  ref
) {
  const optionMap = Object.fromEntries(options.map((o) => [o.value, o]));

  return (
    <Select
      value={value === "" ? null : value}
      onValueChange={(v: string | null) => onValueChange(v ?? "")}
      disabled={disabled}
    >
      <SelectTrigger ref={ref} className={cn("w-full", className)} aria-invalid={invalid || undefined}>
        <SelectValue placeholder={placeholder}>
          {(val: string | null) => {
            if (!val) return placeholder;
            const opt = optionMap[val];
            if (!opt) return val;
            return (
              <>
                {opt.icon && <span className="shrink-0 d-text-primary [&_svg]:size-3.5">{opt.icon}</span>}
                {opt.label}
              </>
            );
          }}
        </SelectValue>
      </SelectTrigger>
      <SelectContent>
        {options.map((opt) => (
          <SelectItem key={opt.value} value={opt.value} disabled={opt.disabled}>
            {opt.icon && <span className="shrink-0 d-text-primary [&_svg]:size-4">{opt.icon}</span>}
            {opt.label}
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  );
});

/* ─────────────────────────────────────────
   Searchable Select (Base UI Combobox)
───────────────────────────────────────── */
const SearchableSelect = React.forwardRef<
  HTMLButtonElement,
  Omit<SelectAppProps, "searchable">
>(function SearchableSelect(
  { value, onValueChange, options, placeholder, searchPlaceholder, disabled, invalid, className },
  ref
) {
  const [query, setQuery] = React.useState("");
  const selected = options.find((o) => o.value === value) ?? null;

  const normalize = (s: string) =>
    s.trim().toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");

  const filtered = query
    ? options.filter((o) => normalize(o.label).includes(normalize(query)))
    : options;

  return (
    <Combobox.Root
      value={value === "" ? null : value}
      onValueChange={(v) => onValueChange(v ?? "")}
      onOpenChange={(open) => { if (!open) setQuery(""); }}
      disabled={disabled}
    >
      {/* Trigger — tampilkan nilai terpilih, buka popup saat diklik */}
      <Combobox.Trigger
        ref={ref as any}
        aria-invalid={invalid || undefined}
        className={cn(
          "flex h-8 w-full items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent pl-2.5 pr-2 text-sm transition-colors outline-none select-none",
          "focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50",
          "disabled:cursor-not-allowed disabled:opacity-50",
          "aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20",
          "dark:bg-input/30",
          className
        )}
      >
        <span className="flex flex-1 items-center gap-1.5 min-w-0">
          {selected?.icon && (
            <span className="shrink-0 d-text-primary [&_svg]:size-3.5">{selected.icon}</span>
          )}
          <span className={cn("truncate", !selected && "text-muted-foreground")}>
            {selected ? selected.label : placeholder}
          </span>
        </span>
        <ChevronDownIcon className="size-4 text-muted-foreground shrink-0" />
      </Combobox.Trigger>

      <Combobox.Portal>
        <Combobox.Positioner sideOffset={4} className="isolate z-50">
          <Combobox.Popup className="w-(--anchor-width) min-w-48 overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2">
            {/* Search input */}
            <div className="flex items-center gap-2 border-b border-border px-2.5 py-1.5">
              <SearchIcon className="size-3.5 text-muted-foreground shrink-0" />
              <Combobox.Input
                autoFocus
                value={query}
                onChange={(e) => setQuery(e.target.value)}
                placeholder={searchPlaceholder}
                className="flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
              />
            </div>

            <Combobox.List className="max-h-60 overflow-y-auto p-1 scrollbar-thin">
              {filtered.length === 0 && (
                <div className="py-6 text-center text-sm text-muted-foreground">
                  Tidak ditemukan.
                </div>
              )}
              {filtered.map((opt) => (
                <Combobox.Item
                  key={opt.value}
                  value={opt.value}
                  disabled={opt.disabled}
                  className="relative flex cursor-default items-center gap-2 rounded-md px-2 py-1.5 text-sm outline-none select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50"
                >
                  {opt.icon && (
                    <span className="shrink-0 d-text-secondary [&_svg]:size-4">{opt.icon}</span>
                  )}
                  <span className="flex-1 truncate">{opt.label}</span>
                  <Combobox.ItemIndicator className="ml-auto">
                    <CheckIcon className="size-3.5 d-text-primary" />
                  </Combobox.ItemIndicator>
                </Combobox.Item>
              ))}
            </Combobox.List>
          </Combobox.Popup>
        </Combobox.Positioner>
      </Combobox.Portal>
    </Combobox.Root>
  );
});
