"use client";

import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { cn } from "@/lib/utils";

// 검색 가능한 일반 셀렉트박스
// value/label 배열을 직접 받아서 사용 (API 호출 없음)
// 드롭다운은 document.body로 portal → overflow-auto 부모에 의한 클립 방지
interface SearchableSelectProps {
  options: { value: string; label: string }[];
  value?: string;
  onChange?: (value: string) => void;
  placeholder?: string;
  className?: string;
  disabled?: boolean;
  emptyLabel?: string;   // "(선택 안 함)" 대체 텍스트 (빈 문자열이면 미표시)
  showEmpty?: boolean;   // 빈 선택 옵션 표시 여부 (기본 true)
}

export function SearchableSelect({
  options,
  value = "",
  onChange,
  placeholder = "선택",
  className,
  disabled,
  emptyLabel = "(선택 안 함)",
  showEmpty = true,
}: SearchableSelectProps) {
  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState("");
  const [rect, setRect] = useState<{ left: number; top: number; width: number } | null>(null);
  const wrapRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  const selected = options.find((o) => o.value === value);
  const filtered = useMemo(() => {
    if (!search) return options;
    const s = search.toLowerCase();
    return options.filter(
      (o) => o.label.toLowerCase().includes(s) || o.value.toLowerCase().includes(s)
    );
  }, [options, search]);

  // 드롭다운 위치 계산 (스크롤/리사이즈 대응)
  useLayoutEffect(() => {
    if (!open) return;
    const update = () => {
      const el = wrapRef.current;
      if (!el) return;
      const r = el.getBoundingClientRect();
      setRect({ left: r.left, top: r.bottom + 2, width: r.width });
    };
    update();
    window.addEventListener("scroll", update, true);
    window.addEventListener("resize", update);
    return () => {
      window.removeEventListener("scroll", update, true);
      window.removeEventListener("resize", update);
    };
  }, [open]);

  // 외부 클릭 닫기
  useEffect(() => {
    if (!open) return;
    const onDown = (e: MouseEvent) => {
      const target = e.target as Node;
      if (wrapRef.current?.contains(target)) return;
      // 드롭다운 자체 클릭은 onMouseDown 이 먼저 처리하므로 여기서 닫아도 OK
      setOpen(false);
    };
    document.addEventListener("mousedown", onDown);
    return () => document.removeEventListener("mousedown", onDown);
  }, [open]);

  const close = () => { setOpen(false); setSearch(""); };

  return (
    <div ref={wrapRef} className={cn("relative", className)}>
      <input
        ref={inputRef}
        type="text"
        value={open ? search : (selected?.label || "")}
        placeholder={placeholder}
        disabled={disabled}
        onFocus={() => { setOpen(true); setSearch(""); }}
        onChange={(e) => setSearch(e.target.value)}
        className={cn(
          "h-9 w-full rounded border border-gray-300 bg-white pl-2 pr-7 text-sm outline-none",
          "focus:border-primary focus:ring-1 focus:ring-primary/50",
          "disabled:cursor-not-allowed disabled:opacity-50"
        )}
      />
      {selected && !open && !disabled && (
        <button
          type="button"
          onClick={() => { onChange?.(""); setSearch(""); }}
          className="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-700 text-sm leading-none"
          aria-label="선택 해제"
          tabIndex={-1}
        >
          ×
        </button>
      )}
      {!selected && !open && (
        <span className="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 text-xs pointer-events-none">▾</span>
      )}
      {open && rect && typeof document !== "undefined" && createPortal(
        <div
          style={{
            position: "fixed",
            left: rect.left,
            top: rect.top,
            width: rect.width,
            zIndex: 9999,
          }}
          className="max-h-56 overflow-y-auto bg-white border border-gray-300 rounded shadow-lg"
        >
          {showEmpty && (
            <button
              type="button"
              onMouseDown={(e) => {
                e.preventDefault();
                onChange?.("");
                close();
              }}
              className="w-full text-left px-2 py-1.5 text-sm text-gray-500 italic hover:bg-gray-50 border-b"
            >
              {emptyLabel}
            </button>
          )}
          {filtered.length === 0 ? (
            <div className="p-2 text-xs text-gray-400 text-center">결과 없음</div>
          ) : (
            filtered.map((o) => (
              <button
                key={o.value}
                type="button"
                onMouseDown={(e) => {
                  e.preventDefault();
                  onChange?.(o.value);
                  close();
                }}
                className={cn(
                  "w-full text-left px-2 py-1.5 text-sm hover:bg-blue-50",
                  o.value === value && "bg-blue-50"
                )}
              >
                {o.label}
              </button>
            ))
          )}
        </div>,
        document.body,
      )}
    </div>
  );
}
