"use client";

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

// 검색 가능한 공통코드 셀렉트박스. CodeSelect와 동일 데이터를 쓰지만 typeahead 지원.
// 드롭다운은 document.body로 portal → overflow-auto 부모에 의한 클립 방지
interface SearchableCodeSelectProps {
  codeId: string;
  value?: string;
  onChange?: (value: string) => void;
  placeholder?: string;
  className?: string;
  disabled?: boolean;
  showCodeId?: boolean;   // 드롭다운에 CODE_ID 같이 표시 여부
  emptyLabel?: string;    // 빈 선택 표시 텍스트 (기본 "(선택 안 함)")
}

interface Option { CODE_ID: string; CODE_NAME: string }

export function SearchableCodeSelect({
  codeId,
  value = "",
  onChange,
  placeholder = "선택",
  className,
  disabled,
  showCodeId = false,
  emptyLabel = "(선택 안 함)",
}: SearchableCodeSelectProps) {
  const [options, setOptions] = useState<Option[]>([]);
  const [loading, setLoading] = useState(false);
  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);

  useEffect(() => {
    if (!codeId) return;
    setLoading(true);
    fetch("/api/common/code-list", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ codeId }),
    })
      .then((r) => r.json())
      .then((d) => {
        const rows = (d.data || []) as Array<Record<string, unknown>>;
        setOptions(
          rows.map((r) => ({
            CODE_ID: String(r.code_id || r.CODE_ID || ""),
            CODE_NAME: String(r.code_name || r.CODE_NAME || ""),
          }))
        );
      })
      .catch(() => setOptions([]))
      .finally(() => setLoading(false));
  }, [codeId]);

  const selected = options.find((o) => o.CODE_ID === value);
  const filtered = useMemo(() => {
    if (!search) return options;
    const s = search.toLowerCase();
    return options.filter(
      (o) => o.CODE_NAME.toLowerCase().includes(s) || o.CODE_ID.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;
      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
        type="text"
        value={open ? search : (selected?.CODE_NAME || "")}
        placeholder={loading ? "로딩중..." : placeholder}
        disabled={disabled || loading}
        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"
        >
          <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.CODE_ID}
                type="button"
                onMouseDown={(e) => {
                  e.preventDefault();
                  onChange?.(o.CODE_ID);
                  close();
                }}
                className={cn(
                  "w-full text-left px-2 py-1.5 text-sm hover:bg-blue-50 flex items-center gap-2",
                  o.CODE_ID === value && "bg-blue-50"
                )}
              >
                {showCodeId && (
                  <span className="text-[11px] text-gray-400 font-mono shrink-0 w-[70px]">{o.CODE_ID}</span>
                )}
                <span className="truncate">{o.CODE_NAME}</span>
              </button>
            ))
          )}
        </div>,
        document.body,
      )}
    </div>
  );
}
