"use client";

/**
 * 변수 태그 에디터 컴포넌트
 * TipTap 기반으로 본문 내에서 변수를 시각적 태그로 표시하고 삽입할 수 있는 에디터
 */

import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useEditor, EditorContent, BubbleMenu } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import Placeholder from "@tiptap/extension-placeholder";
import {
  VariableTagExtension,
  textToEditorContent,
  editorContentToText,
} from "./VariableTagExtension";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command";
import { Plus, Variable, X, Search } from "lucide-react";
import { cn } from "@/lib/utils";

// 변수 정보 타입
export interface VariableInfo {
  name: string; // 실제 변수명 (예: customerName)
  displayName: string; // 표시명 (예: 고객명)
  type?: string; // 데이터 타입 (예: string, number)
  description?: string; // 설명
}

interface VariableTagEditorProps {
  value: string; // 현재 값 (예: "안녕하세요, {{customerName}} 님")
  onChange: (value: string) => void; // 값 변경 콜백
  variables: VariableInfo[]; // 사용 가능한 변수 목록
  placeholder?: string;
  className?: string;
  minHeight?: string;
  disabled?: boolean;
}

export function VariableTagEditor({
  value,
  onChange,
  variables,
  placeholder = "내용을 입력하세요...",
  className,
  minHeight = "150px",
  disabled = false,
}: VariableTagEditorProps) {
  const [isVariablePopoverOpen, setIsVariablePopoverOpen] = useState(false);
  const [searchQuery, setSearchQuery] = useState("");

  // 변수명 → 표시명 맵 생성
  const variableMap = useMemo(() => {
    const map: Record<string, string> = {};
    variables.forEach((v) => {
      map[v.name] = v.displayName;
    });
    return map;
  }, [variables]);

  // 필터된 변수 목록
  const filteredVariables = useMemo(() => {
    if (!searchQuery) return variables;
    const query = searchQuery.toLowerCase();
    return variables.filter(
      (v) =>
        v.name.toLowerCase().includes(query) ||
        v.displayName.toLowerCase().includes(query)
    );
  }, [variables, searchQuery]);

  // TipTap 에디터 초기화
  const editor = useEditor({
    extensions: [
      StarterKit.configure({
        // 불필요한 기능 비활성화
        heading: false,
        bulletList: false,
        orderedList: false,
        blockquote: false,
        codeBlock: false,
        horizontalRule: false,
      }),
      VariableTagExtension,
      Placeholder.configure({
        placeholder,
        emptyEditorClass: "is-editor-empty",
      }),
    ],
    content: textToEditorContent(value, variableMap),
    editable: !disabled,
    onUpdate: ({ editor }) => {
      const json = editor.getJSON();
      const text = editorContentToText(json);
      onChange(text);
    },
    editorProps: {
      attributes: {
        class: cn(
          "prose prose-sm max-w-none focus:outline-none",
          "min-h-[100px] p-3",
          disabled && "opacity-50 cursor-not-allowed"
        ),
      },
    },
  });

  // 외부 value 변경 시 에디터 동기화
  useEffect(() => {
    if (editor && !editor.isFocused) {
      const currentText = editorContentToText(editor.getJSON());
      if (currentText !== value) {
        editor.commands.setContent(textToEditorContent(value, variableMap));
      }
    }
  }, [value, editor, variableMap]);

  // 변수 삽입
  const insertVariable = useCallback(
    (variable: VariableInfo) => {
      if (!editor) return;

      editor
        .chain()
        .focus()
        .insertContent({
          type: "variableTag",
          attrs: {
            variableName: variable.name,
            displayName: variable.displayName,
          },
        })
        .run();

      setIsVariablePopoverOpen(false);
      setSearchQuery("");
    },
    [editor]
  );

  // @ 키 입력 시 변수 팝업 표시
  useEffect(() => {
    if (!editor) return;

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === "@" || (event.key === "/" && !event.shiftKey)) {
        event.preventDefault();
        setIsVariablePopoverOpen(true);
      }
    };

    const editorElement = editor.view.dom;
    editorElement.addEventListener("keydown", handleKeyDown);

    return () => {
      editorElement.removeEventListener("keydown", handleKeyDown);
    };
  }, [editor]);

  if (!editor) {
    return null;
  }

  return (
    <div className={cn("relative rounded-md border", className)}>
      {/* 툴바 */}
      <div className="flex items-center justify-between border-b bg-muted px-2 py-1">
        <div className="flex items-center gap-1">
          <Popover
            open={isVariablePopoverOpen}
            onOpenChange={setIsVariablePopoverOpen}
          >
            <PopoverTrigger asChild>
              <Button
                type="button"
                variant="ghost"
                size="sm"
                className="h-7 gap-1 text-xs"
                disabled={disabled}
              >
                <Variable className="h-3.5 w-3.5" />
                변수 삽입
              </Button>
            </PopoverTrigger>
            <PopoverContent className="w-[280px] p-0" align="start">
              <Command>
                <CommandInput
                  placeholder="변수 검색..."
                  value={searchQuery}
                  onValueChange={setSearchQuery}
                />
                <CommandList>
                  <CommandEmpty>검색 결과가 없습니다</CommandEmpty>
                  <CommandGroup heading="사용 가능한 변수">
                    {filteredVariables.map((variable) => (
                      <CommandItem
                        key={variable.name}
                        value={`${variable.name}-${variable.displayName}`}
                        onSelect={() => insertVariable(variable)}
                        className="cursor-pointer"
                      >
                        <div className="flex flex-col">
                          <div className="flex items-center gap-2">
                            <span className="rounded bg-primary/10 px-1.5 py-0.5 text-xs font-medium text-primary">
                              {variable.displayName}
                            </span>
                            <span className="text-xs text-muted-foreground">
                              {variable.name}
                            </span>
                          </div>
                          {variable.description && (
                            <span className="mt-0.5 text-xs text-muted-foreground/70">
                              {variable.description}
                            </span>
                          )}
                        </div>
                      </CommandItem>
                    ))}
                  </CommandGroup>
                </CommandList>
              </Command>
            </PopoverContent>
          </Popover>
        </div>

        <div className="text-xs text-muted-foreground/70">
          <kbd className="rounded bg-muted/80 px-1">@</kbd> 또는{" "}
          <kbd className="rounded bg-muted/80 px-1">/</kbd> 로 변수 삽입
        </div>
      </div>

      {/* 에디터 영역 */}
      <div style={{ minHeight }}>
        <EditorContent editor={editor} />
      </div>

      {/* 스타일 */}
      <style jsx global>{`
        /* 변수 태그 스타일 */
        .variable-tag {
          display: inline-flex;
          align-items: center;
          background-color: #dbeafe;
          color: #1d4ed8;
          padding: 1px 6px;
          border-radius: 4px;
          font-size: 0.875rem;
          font-weight: 500;
          cursor: default;
          user-select: none;
          margin: 0 1px;
          vertical-align: baseline;
        }

        .variable-tag:hover {
          background-color: #bfdbfe;
        }

        /* 선택된 태그 */
        .variable-tag.ProseMirror-selectednode {
          outline: 2px solid #3b82f6;
          outline-offset: 1px;
        }

        /* 플레이스홀더 스타일 */
        .is-editor-empty:first-child::before {
          content: attr(data-placeholder);
          float: left;
          color: #9ca3af;
          pointer-events: none;
          height: 0;
        }

        /* 에디터 기본 스타일 */
        .ProseMirror {
          outline: none;
        }

        .ProseMirror p {
          margin: 0.5em 0;
        }

        .ProseMirror p:first-child {
          margin-top: 0;
        }

        .ProseMirror p:last-child {
          margin-bottom: 0;
        }
      `}</style>
    </div>
  );
}

export default VariableTagEditor;

