"use client";

import { useState, useCallback, useEffect, useRef, useMemo } from "react";
import { Search, X } from "lucide-react";
import { NODE_PALETTE, NODE_CATEGORIES } from "./sidebar/nodePaletteConfig";
import type { NodePaletteItem } from "@/types/node-editor";

const TOSS_CATEGORY_LABELS: Record<string, string> = {
  source: "데이터를 가져와요",
  transform: "데이터를 가공해요",
  action: "데이터를 저장해요",
  external: "외부로 연결해요",
  utility: "도구",
};

const TOSS_NODE_DESCRIPTIONS: Record<string, string> = {
  tableSource: "내부 데이터베이스에서 데이터를 읽어와요",
  externalDBSource: "외부 데이터베이스에 연결해서 데이터를 가져와요",
  restAPISource: "REST API를 호출해서 데이터를 받아와요",
  condition: "조건에 따라 데이터 흐름을 나눠요",
  dataTransform: "데이터를 원하는 형태로 바꿔요",
  aggregate: "합계, 평균 등 집계 연산을 수행해요",
  formulaTransform: "수식을 이용해서 새로운 값을 계산해요",
  insertAction: "데이터를 테이블에 새로 추가해요",
  updateAction: "기존 데이터를 수정해요",
  deleteAction: "데이터를 삭제해요",
  upsertAction: "있으면 수정하고, 없으면 새로 추가해요",
  emailAction: "이메일을 자동으로 보내요",
  scriptAction: "외부 스크립트를 실행해요",
  httpRequestAction: "HTTP 요청을 보내요",
  procedureCallAction: "DB 프로시저를 호출해요",
  comment: "메모를 남겨요",
};

interface CommandPaletteProps {
  isOpen: boolean;
  onClose: () => void;
  onSelectNode: (nodeType: string) => void;
}

export function CommandPalette({ isOpen, onClose, onSelectNode }: CommandPaletteProps) {
  const [query, setQuery] = useState("");
  const [focusIndex, setFocusIndex] = useState(0);
  const inputRef = useRef<HTMLInputElement>(null);
  const listRef = useRef<HTMLDivElement>(null);

  const filteredItems = useMemo(() => {
    if (!query.trim()) return NODE_PALETTE;
    const q = query.toLowerCase();
    return NODE_PALETTE.filter(
      (item) =>
        item.label.toLowerCase().includes(q) ||
        item.description.toLowerCase().includes(q) ||
        item.type.toLowerCase().includes(q) ||
        (TOSS_NODE_DESCRIPTIONS[item.type] || "").toLowerCase().includes(q),
    );
  }, [query]);

  const groupedItems = useMemo(() => {
    const groups: { category: string; label: string; items: NodePaletteItem[] }[] = [];
    for (const cat of NODE_CATEGORIES) {
      const items = filteredItems.filter((i) => i.category === cat.id);
      if (items.length > 0) {
        groups.push({
          category: cat.id,
          label: TOSS_CATEGORY_LABELS[cat.id] || cat.label,
          items,
        });
      }
    }
    return groups;
  }, [filteredItems]);

  const flatItems = useMemo(() => groupedItems.flatMap((g) => g.items), [groupedItems]);

  useEffect(() => {
    if (isOpen) {
      setQuery("");
      setFocusIndex(0);
      setTimeout(() => inputRef.current?.focus(), 50);
    }
  }, [isOpen]);

  useEffect(() => {
    setFocusIndex(0);
  }, [query]);

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent) => {
      if (e.key === "Escape") {
        onClose();
      } else if (e.key === "ArrowDown") {
        e.preventDefault();
        setFocusIndex((i) => Math.min(i + 1, flatItems.length - 1));
      } else if (e.key === "ArrowUp") {
        e.preventDefault();
        setFocusIndex((i) => Math.max(i - 1, 0));
      } else if (e.key === "Enter" && flatItems[focusIndex]) {
        onSelectNode(flatItems[focusIndex].type);
        onClose();
      }
    },
    [flatItems, focusIndex, onClose, onSelectNode],
  );

  useEffect(() => {
    const focused = listRef.current?.querySelector('[data-focused="true"]');
    focused?.scrollIntoView({ block: "nearest" });
  }, [focusIndex]);

  if (!isOpen) return null;

  return (
    <div className="fixed inset-0 z-[100] flex items-start justify-center pt-[15vh]">
      {/* backdrop */}
      <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={onClose} />

      {/* palette */}
      <div className="relative w-full max-w-[520px] overflow-hidden rounded-xl border border-zinc-700 bg-zinc-900 shadow-2xl shadow-black/50">
        {/* 검색 */}
        <div className="flex items-center gap-3 border-b border-zinc-800 px-4 py-3">
          <Search className="h-4 w-4 flex-shrink-0 text-zinc-500" />
          <input
            ref={inputRef}
            type="text"
            value={query}
            onChange={(e) => setQuery(e.target.value)}
            onKeyDown={handleKeyDown}
            placeholder="어떤 노드를 추가할까요?"
            className="flex-1 bg-transparent text-sm text-zinc-200 outline-none placeholder:text-zinc-600"
          />
          <button
            onClick={onClose}
            className="flex h-6 w-6 items-center justify-center rounded text-zinc-500 transition-colors hover:text-zinc-300"
          >
            <X className="h-4 w-4" />
          </button>
        </div>

        {/* 목록 */}
        <div ref={listRef} className="max-h-[360px] overflow-y-auto p-2">
          {groupedItems.length === 0 ? (
            <div className="py-8 text-center text-sm text-zinc-500">
              &ldquo;{query}&rdquo;에 해당하는 노드를 찾지 못했어요
            </div>
          ) : (
            groupedItems.map((group) => {
              let groupStartIdx = 0;
              for (const g of groupedItems) {
                if (g.category === group.category) break;
                groupStartIdx += g.items.length;
              }

              return (
                <div key={group.category} className="mb-1">
                  <div className="px-2 py-1.5 text-[11px] font-semibold uppercase tracking-wider text-zinc-500">
                    {group.label}
                  </div>
                  {group.items.map((item, idx) => {
                    const globalIdx = groupStartIdx + idx;
                    const isFocused = globalIdx === focusIndex;
                    return (
                      <button
                        key={item.type}
                        data-focused={isFocused}
                        className={`flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-left transition-colors ${
                          isFocused ? "bg-violet-500/15 text-zinc-100" : "text-zinc-300 hover:bg-zinc-800"
                        }`}
                        onClick={() => {
                          onSelectNode(item.type);
                          onClose();
                        }}
                        onMouseEnter={() => setFocusIndex(globalIdx)}
                      >
                        <div
                          className="h-2 w-2 flex-shrink-0 rounded-full"
                          style={{ backgroundColor: item.color }}
                        />
                        <div className="min-w-0 flex-1">
                          <div className="text-sm font-medium">{item.label}</div>
                          <div className="truncate text-[11px] text-zinc-500">
                            {TOSS_NODE_DESCRIPTIONS[item.type] || item.description}
                          </div>
                        </div>
                      </button>
                    );
                  })}
                </div>
              );
            })
          )}
        </div>

        {/* 하단 힌트 */}
        <div className="flex items-center gap-4 border-t border-zinc-800 px-4 py-2 text-[11px] text-zinc-600">
          <span>
            <kbd className="rounded border border-zinc-700 bg-zinc-800 px-1 py-0.5 font-mono text-[10px]">
              Enter
            </kbd>{" "}
            선택
          </span>
          <span>
            <kbd className="rounded border border-zinc-700 bg-zinc-800 px-1 py-0.5 font-mono text-[10px]">
              Esc
            </kbd>{" "}
            닫기
          </span>
          <span>
            <kbd className="rounded border border-zinc-700 bg-zinc-800 px-1 py-0.5 font-mono text-[10px]">
              ↑↓
            </kbd>{" "}
            이동
          </span>
        </div>
      </div>
    </div>
  );
}
