"use client";

import React, { useCallback, useEffect } from "react";
import toast from "react-hot-toast";
import { ReactFlow, Controls, Background, BackgroundVariant, SelectionMode, Node, Edge } from "@xyflow/react";
import "@xyflow/react/dist/style.css";

import { TableNode } from "./TableNode";
import { ConnectionSetupModal } from "./ConnectionSetupModal";
import { DataFlowSidebar } from "./DataFlowSidebar";
import { SelectedTablesPanel } from "./SelectedTablesPanel";
import { RelationshipListModal } from "./RelationshipListModal";
import { EdgeInfoPanel } from "./EdgeInfoPanel";
import SaveDiagramModal from "./SaveDiagramModal";

import {
  TableDefinition,
  DataFlowAPI,
  JsonRelationship,
  TableRelationship,
  CreateDiagramRequest,
} from "@/lib/api/dataflow";
import { useAuth } from "@/hooks/useAuth";
import { useDataFlowDesigner } from "@/hooks/useDataFlowDesigner";
import { DataFlowDesignerProps, TableNodeData } from "@/types/dataflowTypes";
import { extractTableNames, extractNodePositions } from "@/utils/dataflowUtils";

// 노드 및 엣지 타입 정의
const nodeTypes = {
  tableNode: TableNode,
};

const edgeTypes = {};

export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({
  companyCode: propCompanyCode = "*",
  diagramId,
}) => {
  const { user: authUser } = useAuth();

  // 실제 사용자 회사 코드 사용 (prop보다 사용자 정보 우선)
  const companyCode = authUser?.company_code || authUser?.companyCode || propCompanyCode;

  // 커스텀 훅 사용
  const {
    nodes,
    setNodes,
    onNodesChange,
    edges,
    setEdges,
    onEdgesChange,
    selectedColumns,
    setSelectedColumns,
    selectedNodes,
    setSelectedNodes,
    pendingConnection,
    setPendingConnection,
    currentDiagramId,
    setCurrentDiagramId,
    currentDiagramName,
    setCurrentDiagramName,
    currentDiagramCategory,
    tempRelationships,
    setTempRelationships,
    hasUnsavedChanges,
    setHasUnsavedChanges,
    showSaveModal,
    setShowSaveModal,
    isSaving,
    setIsSaving,
    showRelationshipListModal,
    setShowRelationshipListModal,
    selectedTablePairRelationships,
    setSelectedTablePairRelationships,
    selectedEdgeInfo,
    setSelectedEdgeInfo,
    setSelectedEdgeForEdit,
    showEdgeActions,
    setShowEdgeActions,
    edgeActionPosition,
    editingRelationshipId,
    setEditingRelationshipId,
  } = useDataFlowDesigner();

  // 컬럼 클릭 처리 비활성화 (테이블 노드 선택 방식으로 변경)
  const handleColumnClick = useCallback((tableName: string, columnName: string) => {
    // 컬럼 클릭으로는 더 이상 선택하지 않음
    console.log(`컬럼 클릭 무시됨: ${tableName}.${columnName}`);
    return;
  }, []);

  // 편집 모드일 때 관계 데이터 로드
  useEffect(() => {
    const loadDiagramData = async () => {
      if (diagramId && diagramId > 0) {
        try {
          // 편집 모드일 때 currentDiagramId 설정
          setCurrentDiagramId(diagramId);

          const jsonDiagram = await DataFlowAPI.getJsonDataFlowDiagramById(diagramId, companyCode);
          if (jsonDiagram) {
            // 관계 이름 설정
            if (jsonDiagram.diagram_name) {
              setCurrentDiagramName(jsonDiagram.diagram_name);
            }

            // 관계 데이터 로드
            if (jsonDiagram.relationships?.relationships && Array.isArray(jsonDiagram.relationships.relationships)) {
              const loadedRelationships = jsonDiagram.relationships.relationships.map((rel) => ({
                id: rel.id || `rel-${Date.now()}-${Math.random()}`,
                fromTable: rel.fromTable,
                toTable: rel.toTable,
                fromColumns: Array.isArray(rel.fromColumns) ? rel.fromColumns : [],
                toColumns: Array.isArray(rel.toColumns) ? rel.toColumns : [],
                connectionType: rel.connectionType || "simple-key",
                relationshipName: rel.relationshipName || "",
                note: rel.note || "", // 🔥 연결 설명 로드
              }));

              setTempRelationships(loadedRelationships);

              // 관계 데이터로부터 테이블 노드들을 생성
              const tableNames = new Set<string>();
              loadedRelationships.forEach((rel) => {
                tableNames.add(rel.fromTable);
                tableNames.add(rel.toTable);
              });

              // 각 테이블의 정보를 API에서 가져와서 노드 생성
              const loadedNodes = await Promise.all(
                Array.from(tableNames).map(async (tableName) => {
                  try {
                    const columns = await DataFlowAPI.getTableColumns(tableName);
                    return {
                      id: `table-${tableName}`,
                      type: "tableNode",
                      position: jsonDiagram.node_positions?.[tableName] || {
                        x: Math.random() * 300,
                        y: Math.random() * 200,
                      },
                      data: {
                        table: {
                          tableName,
                          displayName: tableName,
                          description: "",
                          columns: Array.isArray(columns)
                            ? columns.map((col) => ({
                                name: col.columnName || "unknown",
                                type: col.dataType || "varchar",
                                description: col.description || "",
                              }))
                            : [],
                        },
                        onColumnClick: handleColumnClick,
                        selectedColumns: [],
                        connectedColumns: {},
                      },
                      selected: false,
                    };
                  } catch (error) {
                    console.warn(`테이블 ${tableName} 정보 로드 실패:`, error);
                    return {
                      id: `table-${tableName}`,
                      type: "tableNode",
                      position: jsonDiagram.node_positions?.[tableName] || {
                        x: Math.random() * 300,
                        y: Math.random() * 200,
                      },
                      data: {
                        table: {
                          tableName,
                          displayName: tableName,
                          description: "",
                          columns: [],
                        },
                        onColumnClick: handleColumnClick,
                        selectedColumns: [],
                        connectedColumns: {},
                      },
                      selected: false,
                    };
                  }
                }),
              );

              setNodes(loadedNodes);

              // 관계 데이터로부터 엣지 생성
              const loadedEdges = loadedRelationships.map((rel) => ({
                id: `edge-${rel.fromTable}-${rel.toTable}-${rel.id}`,
                source: `table-${rel.fromTable}`,
                target: `table-${rel.toTable}`,
                type: "step",
                data: {
                  relationshipId: rel.id,
                  fromTable: rel.fromTable,
                  toTable: rel.toTable,
                  connectionType: rel.connectionType,
                  relationshipName: rel.relationshipName,
                },
                style: {
                  stroke: "#3b82f6",
                  strokeWidth: 2,
                },
                animated: false,
              }));

              setEdges(loadedEdges);
            }
          }
        } catch (error) {
          console.error("관계도 데이터 로드 실패:", error);
          toast.error("관계도를 불러오는데 실패했습니다.");
        }
      } else {
        // 신규 생성 모드
        setCurrentDiagramName("");
        setNodes([]);
        setEdges([]);
        setTempRelationships([]);
      }
    };

    loadDiagramData();
  }, [
    diagramId,
    companyCode,
    setCurrentDiagramId,
    setCurrentDiagramName,
    setNodes,
    setEdges,
    setTempRelationships,
    handleColumnClick,
  ]);

  // 키보드 이벤트 핸들러 (Del 키로 선택된 노드 삭제)
  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === "Delete" && selectedNodes.length > 0) {
        // 선택된 노드들 삭제
        setNodes((prevNodes) => prevNodes.filter((node) => !selectedNodes.includes(node.id)));

        // 삭제된 노드들과 관련된 선택된 컬럼들도 정리
        const deletedTableNames = selectedNodes
          .filter((nodeId) => nodeId.startsWith("table-"))
          .map((nodeId) => nodeId.replace("table-", ""));

        setSelectedColumns((prev) => {
          const newColumns = { ...prev };
          deletedTableNames.forEach((tableName) => {
            delete newColumns[tableName];
          });
          return newColumns;
        });

        // 선택된 노드 초기화
        setSelectedNodes([]);

        toast.success(`${selectedNodes.length}개 테이블이 삭제되었습니다.`);
      }
    };

    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [selectedNodes, setNodes, setSelectedColumns, setSelectedNodes]);

  // 현재 추가된 테이블명 목록 가져오기
  const getSelectedTableNames = useCallback(() => {
    return extractTableNames(nodes);
  }, [nodes]);

  // 실제 테이블 노드 추가
  const addTableNode = useCallback(
    async (table: TableDefinition) => {
      try {
        const newNode = {
          id: `table-${table.tableName}`,
          type: "tableNode",
          position: { x: Math.random() * 300, y: Math.random() * 200 },
          data: {
            table: {
              tableName: table.tableName,
              displayName: table.displayName || table.tableName,
              description: "", // 새로 추가된 노드는 description 없이 통일
              columns: Array.isArray(table.columns)
                ? table.columns.map((col) => ({
                    columnName: col.columnName || "unknown",
                    name: col.columnName || "unknown", // 호환성을 위해 유지
                    displayName: col.displayName, // 한국어 라벨
                    columnLabel: col.columnLabel, // 한국어 라벨
                    type: col.dataType || "varchar",
                    dataType: col.dataType || "varchar",
                    description: col.description || "",
                  }))
                : [],
            },
            onColumnClick: handleColumnClick,
            selectedColumns: selectedColumns[table.tableName] || [],
            connectedColumns: {}, // 새로 추가된 노드는 연결 정보 없음
          },
        };

        setNodes((nds) => nds.concat(newNode));
      } catch (error) {
        console.error("테이블 노드 추가 실패:", error);
        toast.error("테이블 정보를 불러오는데 실패했습니다.");
      }
    },
    [handleColumnClick, selectedColumns, setNodes],
  );

  // 노드 클릭 핸들러 (커스텀 다중 선택 구현)
  const onNodeClick = useCallback(
    (event: React.MouseEvent, node: Node<TableNodeData>) => {
      event.stopPropagation();

      const nodeId = node.id;
      const isCurrentlySelected = selectedNodes.includes(nodeId);

      if (isCurrentlySelected) {
        // 이미 선택된 노드를 클릭하면 선택 해제
        const newSelection = selectedNodes.filter((id) => id !== nodeId);
        setSelectedNodes(newSelection);

        // React Flow 노드 상태 업데이트
        setNodes((prevNodes) =>
          prevNodes.map((n) => ({
            ...n,
            selected: newSelection.includes(n.id),
          })),
        );
      } else {
        // 새로운 노드 선택
        let newSelection: string[];

        if (selectedNodes.length >= 2) {
          // 이미 2개가 선택되어 있으면 첫 번째를 제거하고 새로운 것을 추가 (FIFO)
          newSelection = [selectedNodes[1], nodeId];
        } else {
          // 2개 미만이면 추가
          newSelection = [...selectedNodes, nodeId];
        }

        setSelectedNodes(newSelection);

        // React Flow 노드 상태 업데이트
        setNodes((prevNodes) =>
          prevNodes.map((n) => ({
            ...n,
            selected: newSelection.includes(n.id),
          })),
        );
      }
    },
    [selectedNodes, setNodes, setSelectedNodes],
  );

  // 노드 선택 변경 핸들러 (React Flow 자체 선택 이벤트는 무시)
  const onSelectionChange = useCallback(() => {
    // React Flow의 자동 선택 변경은 무시하고 우리의 커스텀 로직만 사용
    // 이 함수는 비워두거나 최소한의 동기화만 수행
  }, []);

  // 캔버스 클릭 시 엣지 정보 섹션 닫기
  const onPaneClick = useCallback(() => {
    if (selectedEdgeInfo) {
      setSelectedEdgeInfo(null);
    }
    if (showEdgeActions) {
      setShowEdgeActions(false);
      setSelectedEdgeForEdit(null);
    }
    // 컬럼 선택 해제
    setSelectedColumns({});
  }, [
    selectedEdgeInfo,
    showEdgeActions,
    setSelectedEdgeInfo,
    setShowEdgeActions,
    setSelectedEdgeForEdit,
    setSelectedColumns,
  ]);

  // 빈 onConnect 함수 (드래그 연결 비활성화)
  const onConnect = useCallback(() => {
    // 드래그로 연결하는 것을 방지
    return;
  }, []);

  // 엣지 클릭 시 연결 정보 표시 및 관련 컬럼 하이라이트
  const onEdgeClick = useCallback(
    (event: React.MouseEvent, edge: Edge) => {
      event.stopPropagation();
      const edgeData = edge.data;

      if (edgeData) {
        // 해당 테이블 쌍의 모든 관계 찾기
        const fromTable = edgeData.fromTable;
        const toTable = edgeData.toTable;

        const tablePairRelationships = tempRelationships.filter(
          (rel) =>
            (rel.fromTable === fromTable && rel.toTable === toTable) ||
            (rel.fromTable === toTable && rel.toTable === fromTable),
        );

        // 관계가 1개든 여러 개든 항상 관계 목록 모달 표시
        setSelectedTablePairRelationships(tablePairRelationships);
        setShowRelationshipListModal(true);
      }
    },
    [tempRelationships, setSelectedTablePairRelationships, setShowRelationshipListModal],
  );

  // 엣지 마우스 엔터 시 색상 변경
  const onEdgeMouseEnter = useCallback(
    (event: React.MouseEvent, edge: Edge) => {
      setEdges((eds) =>
        eds.map((e) =>
          e.id === edge.id
            ? {
                ...e,
                style: {
                  ...e.style,
                  stroke: "#1d4ed8", // hover 색상
                  strokeWidth: 3,
                },
              }
            : e,
        ),
      );
    },
    [setEdges],
  );

  // 엣지 마우스 리브 시 원래 색상으로 복원
  const onEdgeMouseLeave = useCallback(
    (event: React.MouseEvent, edge: Edge) => {
      setEdges((eds) =>
        eds.map((e) =>
          e.id === edge.id
            ? {
                ...e,
                style: {
                  ...e.style,
                  stroke: "#3b82f6", // 기본 색상
                  strokeWidth: 2,
                },
              }
            : e,
        ),
      );
    },
    [setEdges],
  );

  // 연결 가능한 상태인지 확인
  const canCreateConnection = () => {
    return selectedNodes.length >= 2;
  };

  // 테이블 노드 연결 설정 모달 열기
  const openConnectionModal = () => {
    if (selectedNodes.length < 2) return;

    // 선택된 첫 번째와 두 번째 노드 찾기
    const firstNode = nodes.find((node) => node.id === selectedNodes[0]);
    const secondNode = nodes.find((node) => node.id === selectedNodes[1]);

    if (!firstNode || !secondNode) return;

    setPendingConnection({
      fromNode: {
        id: firstNode.id,
        tableName: firstNode.data.table.tableName,
        displayName: firstNode.data.table.displayName,
      },
      toNode: {
        id: secondNode.id,
        tableName: secondNode.data.table.tableName,
        displayName: secondNode.data.table.displayName,
      },
    });
  };

  // 연결 설정 확인
  const handleConfirmConnection = useCallback(
    (relationshipData: TableRelationship) => {
      if (!pendingConnection || !relationshipData) return;

      if (editingRelationshipId) {
        // 편집 모드: 기존 관계 업데이트
        const updatedRelationship = {
          id: editingRelationshipId,
          fromTable: relationshipData.from_table_name,
          toTable: relationshipData.to_table_name,
          fromColumns: relationshipData.from_column_name ? relationshipData.from_column_name.split(",") : [],
          toColumns: relationshipData.to_column_name ? relationshipData.to_column_name.split(",") : [],
          connectionType: relationshipData.connection_type as "simple-key" | "data-save" | "external-call",
          relationshipName: relationshipData.relationship_name,
          note: (relationshipData.settings as any)?.notes || "", // 🔥 notes를 note로 변환
          settings: relationshipData.settings || {},
        };

        // tempRelationships에서 기존 관계 업데이트
        setTempRelationships((prev) =>
          prev.map((rel) => (rel.id === editingRelationshipId ? updatedRelationship : rel)),
        );

        // 기존 엣지 업데이트
        setEdges((prevEdges) =>
          prevEdges.map((edge) =>
            edge.data?.relationshipId === editingRelationshipId
              ? {
                  ...edge,
                  data: {
                    ...edge.data,
                    relationshipId: editingRelationshipId,
                    fromTable: relationshipData.from_table_name,
                    toTable: relationshipData.to_table_name,
                    connectionType: relationshipData.connection_type,
                    relationshipName: relationshipData.relationship_name,
                  },
                }
              : edge,
          ),
        );

        // 편집 모드 종료
        setEditingRelationshipId(null);
      } else {
        // 새로 생성 모드: 새로운 관계 추가
        const newRelationship = {
          id: `rel-${Date.now()}`,
          fromTable: relationshipData.from_table_name,
          toTable: relationshipData.to_table_name,
          fromColumns: relationshipData.from_column_name ? relationshipData.from_column_name.split(",") : [],
          toColumns: relationshipData.to_column_name ? relationshipData.to_column_name.split(",") : [],
          connectionType: relationshipData.connection_type as "simple-key" | "data-save" | "external-call",
          relationshipName: relationshipData.relationship_name,
          note: (relationshipData.settings as any)?.notes || "", // 🔥 notes를 note로 변환
          settings: relationshipData.settings || {},
        };

        // tempRelationships 상태 업데이트
        setTempRelationships((prev) => [...prev, newRelationship]);

        // 새로운 엣지 생성
        const newEdge = {
          id: `edge-${relationshipData.from_table_name}-${relationshipData.to_table_name}-${Date.now()}`,
          source: `table-${relationshipData.from_table_name}`,
          target: `table-${relationshipData.to_table_name}`,
          type: "step",
          data: {
            relationshipId: newRelationship.id,
            fromTable: relationshipData.from_table_name,
            toTable: relationshipData.to_table_name,
            connectionType: relationshipData.connection_type,
            relationshipName: relationshipData.relationship_name,
          },
          style: {
            stroke: "#3b82f6",
            strokeWidth: 2,
          },
          animated: false,
        };

        // 엣지 추가
        setEdges((prevEdges) => [...prevEdges, newEdge]);
      }

      setPendingConnection(null);
      setHasUnsavedChanges(true);
    },
    [
      pendingConnection,
      setPendingConnection,
      setHasUnsavedChanges,
      setTempRelationships,
      setEdges,
      editingRelationshipId,
      setEditingRelationshipId,
    ],
  );

  // 연결 설정 취소
  const handleCancelConnection = useCallback(() => {
    setPendingConnection(null);
    if (editingRelationshipId) {
      setEditingRelationshipId(null);
      setSelectedColumns({});
    }
  }, [editingRelationshipId, setPendingConnection, setEditingRelationshipId, setSelectedColumns]);

  // 저장 모달 열기
  const handleOpenSaveModal = useCallback(() => {
    setShowSaveModal(true);
  }, [setShowSaveModal]);

  // 저장 모달 닫기
  const handleCloseSaveModal = useCallback(() => {
    if (!isSaving) {
      setShowSaveModal(false);
    }
  }, [isSaving, setShowSaveModal]);

  // 관계도 저장 함수
  const handleSaveDiagram = useCallback(
    async (diagramName: string): Promise<{ success: boolean; error?: string }> => {
      if (nodes.length === 0) {
        toast.error("저장할 테이블이 없습니다.");
        return { success: false, error: "저장할 테이블이 없습니다." };
      }

      setIsSaving(true);
      try {
        // 노드 위치 정보 추출
        const nodePositions = extractNodePositions(nodes);

        // 연결된 테이블 목록 추출
        const tableNames = extractTableNames(nodes);

        // 관계 데이터를 JsonRelationship 형태로 변환 (note 필드 포함)
        const jsonRelationships: JsonRelationship[] = tempRelationships.map((rel) => ({
          id: rel.id,
          relationshipName: rel.relationshipName, // 🔥 핵심: 관계 이름 포함
          fromTable: rel.fromTable,
          toTable: rel.toTable,
          fromColumns: rel.fromColumns,
          toColumns: rel.toColumns,
          connectionType: rel.connectionType,
          note: rel.note, // 🔥 연결 설명 포함
        }));

        // 저장 요청 데이터 구성
        const saveRequest: CreateDiagramRequest = {
          diagram_name: diagramName,
          relationships: {
            relationships: jsonRelationships,
            tables: tableNames,
          },
          node_positions: nodePositions,
          // 카테고리 정보 추가
          category: tempRelationships.map((rel) => ({
            id: rel.id,
            category: rel.connectionType,
          })),
          // 조건부 연결 설정이 있는 경우 추가
          control: tempRelationships
            .filter((rel) => rel.settings?.control)
            .map((rel) => ({
              id: rel.id,
              triggerType: rel.settings?.control?.triggerType || "insert",
              conditions: (rel.settings?.control?.conditionTree || []).map((condition: Record<string, unknown>) => ({
                ...condition,
                logicalOperator:
                  condition.logicalOperator === "AND" || condition.logicalOperator === "OR"
                    ? condition.logicalOperator
                    : undefined,
              })),
            })),
          // 데이터 저장 액션이 있는 경우 추가 (transformFunction 제거)
          plan: tempRelationships
            .filter((rel) => rel.settings?.actions && Array.isArray(rel.settings.actions))
            .map((rel) => ({
              id: rel.id,
              sourceTable: rel.fromTable,
              actions: (rel.settings?.actions || []).map((action: Record<string, unknown>) => ({
                id: action.id as string,
                name: action.name as string,
                actionType: action.actionType as "insert" | "update" | "delete" | "upsert",
                logicalOperator: action.logicalOperator as "AND" | "OR" | undefined, // 논리 연산자 추가
                fieldMappings: ((action.fieldMappings as Record<string, unknown>[]) || []).map(
                  (mapping: Record<string, unknown>) => {
                    // eslint-disable-next-line @typescript-eslint/no-unused-vars
                    const { transformFunction, ...cleanMapping } = mapping;
                    return cleanMapping as any; // transformFunction 제거 후 타입 캐스팅
                  },
                ),
                splitConfig: action.splitConfig,
                conditions: action.conditions,
              })),
            })) as any, // plan 전체를 any로 캐스팅
        };

        if ((diagramId && diagramId > 0) || (currentDiagramId && currentDiagramId > 0)) {
          // 기존 관계도 수정 (prop diagramId 또는 내부 currentDiagramId 사용)
          const targetDiagramId = diagramId || currentDiagramId;
          await DataFlowAPI.updateJsonDataFlowDiagram(
            targetDiagramId!,
            saveRequest,
            companyCode,
            authUser?.userId || "SYSTEM",
          );
        } else {
          // 새로운 관계도 생성
          const newDiagram = await DataFlowAPI.createJsonDataFlowDiagram(
            saveRequest,
            companyCode,
            authUser?.userId || "SYSTEM",
          );

          // 새로 생성된 다이어그램 ID를 내부 상태에 저장 (다음 저장부터는 업데이트 모드)
          setCurrentDiagramId(newDiagram.diagram_id);
          setCurrentDiagramName(newDiagram.diagram_name);
        }

        setHasUnsavedChanges(false);
        // 성공 모달은 SaveDiagramModal에서 처리하므로 여기서는 toast 제거
        return { success: true };
      } catch (error) {
        // 에러 메시지 분석
        let errorMessage = "관계도 저장 중 오류가 발생했습니다.";
        let isDuplicateError = false;

        // Axios 에러 처리
        if (error && typeof error === "object" && "response" in error) {
          const axiosError = error as any;
          if (axiosError.response?.status === 409) {
            // 중복 이름 에러 (409 Conflict)
            errorMessage = "중복된 이름입니다.";
            isDuplicateError = true;
          } else if (axiosError.response?.data?.message) {
            // 백엔드에서 제공한 에러 메시지 사용
            if (axiosError.response.data.message.includes("중복된 이름입니다")) {
              errorMessage = "중복된 이름입니다.";
              isDuplicateError = true;
            } else {
              errorMessage = axiosError.response.data.message;
            }
          }
        } else if (error instanceof Error) {
          if (
            error.message.includes("중복") ||
            error.message.includes("duplicate") ||
            error.message.includes("already exists")
          ) {
            errorMessage = "중복된 이름입니다.";
            isDuplicateError = true;
          } else {
            errorMessage = error.message;
          }
        }

        // 중복 에러가 아닌 경우만 콘솔에 로그 출력
        if (!isDuplicateError) {
          console.error("관계도 저장 실패:", error);
        }

        return { success: false, error: errorMessage };
      } finally {
        setIsSaving(false);
      }
    },
    [
      nodes,
      tempRelationships,
      diagramId,
      currentDiagramId,
      companyCode,
      authUser?.userId,
      setIsSaving,
      setHasUnsavedChanges,
      setShowSaveModal,
      setCurrentDiagramId,
      setCurrentDiagramName,
    ],
  );

  // 고립된 노드 제거 함수
  const removeOrphanedNodes = useCallback(() => {
    toast.success("고립된 노드가 정리되었습니다.");
  }, []);

  // 전체 삭제 핸들러
  const clearNodes = useCallback(() => {
    setNodes([]);
    setEdges([]);
    setTempRelationships([]);
    setSelectedColumns({});
    setSelectedNodes([]);
    setPendingConnection(null);
    setSelectedEdgeInfo(null);
    setShowEdgeActions(false);
    setSelectedEdgeForEdit(null);
    setHasUnsavedChanges(true);

    toast.success("모든 테이블과 관계가 삭제되었습니다.");
  }, [
    setNodes,
    setEdges,
    setTempRelationships,
    setSelectedColumns,
    setSelectedNodes,
    setPendingConnection,
    setSelectedEdgeInfo,
    setShowEdgeActions,
    setSelectedEdgeForEdit,
    setHasUnsavedChanges,
  ]);

  return (
    <div className="data-flow-designer h-screen bg-muted">
      <div className="flex h-full">
        {/* 사이드바 */}
        <DataFlowSidebar
          companyCode={companyCode}
          nodes={nodes}
          edges={edges}
          tempRelationships={tempRelationships}
          hasUnsavedChanges={hasUnsavedChanges}
          currentDiagramId={currentDiagramId}
          currentDiagramCategory={currentDiagramCategory}
          onTableAdd={addTableNode}
          onRemoveOrphanedNodes={removeOrphanedNodes}
          onClearAll={clearNodes}
          onOpenSaveModal={handleOpenSaveModal}
          getSelectedTableNames={getSelectedTableNames}
        />

        {/* React Flow 캔버스 */}
        <div className="relative flex-1">
          <ReactFlow
            className="[&_.react-flow\_\_pane]:cursor-default [&_.react-flow\_\_pane.dragging]:cursor-grabbing"
            nodes={nodes}
            edges={edges}
            onNodesChange={onNodesChange}
            onEdgesChange={onEdgesChange}
            onConnect={onConnect}
            onSelectionChange={onSelectionChange}
            onNodeClick={onNodeClick}
            onPaneClick={onPaneClick}
            onEdgeClick={onEdgeClick}
            onEdgeMouseEnter={onEdgeMouseEnter}
            onEdgeMouseLeave={onEdgeMouseLeave}
            nodeTypes={nodeTypes}
            edgeTypes={edgeTypes}
            fitView
            attributionPosition="bottom-left"
            panOnScroll={false}
            zoomOnScroll={true}
            zoomOnPinch={true}
            panOnDrag={true}
            selectionOnDrag={false}
            multiSelectionKeyCode={null}
            selectNodesOnDrag={false}
            selectionMode={SelectionMode.Partial}
          >
            <Controls />
            <Background variant={BackgroundVariant.Dots} gap={20} size={1} color="#E5E7EB" />

            {/* 관계 목록 모달 */}
            <RelationshipListModal
              isOpen={showRelationshipListModal}
              relationships={selectedTablePairRelationships.map((rel) => {
                // 최신 tempRelationships에서 해당 관계 찾기
                const updatedRel = tempRelationships.find((tempRel) => tempRel.id === rel.id);
                return updatedRel || rel; // 업데이트된 관계가 있으면 사용, 없으면 원본 사용
              })}
              nodes={nodes}
              diagramId={diagramId}
              companyCode={companyCode}
              editingRelationshipId={editingRelationshipId}
              onClose={() => setShowRelationshipListModal(false)}
              onEdit={() => {}}
              onDelete={(relationshipId) => {
                setTempRelationships((prev) => prev.filter((rel) => rel.id !== relationshipId));
                setEdges((prev) => prev.filter((edge) => edge.data?.relationshipId !== relationshipId));
                setHasUnsavedChanges(true);
              }}
              onSetEditingId={setEditingRelationshipId}
              onSetSelectedColumns={setSelectedColumns}
              onSetPendingConnection={setPendingConnection}
            />
          </ReactFlow>

          {/* 선택된 테이블 노드 팝업 */}
          {selectedNodes.length > 0 && !showEdgeActions && !pendingConnection && !editingRelationshipId && (
            <SelectedTablesPanel
              selectedNodes={selectedNodes}
              nodes={nodes}
              onClose={() => setSelectedNodes([])}
              onOpenConnectionModal={openConnectionModal}
              onClear={() => {
                setSelectedColumns({});
                setSelectedNodes([]);
              }}
              canCreateConnection={canCreateConnection()}
            />
          )}

          {/* 안내 메시지 */}
          {nodes.length === 0 && (
            <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
              <div className="text-center text-muted-foreground">
                <div className="mb-2 text-2xl">📊</div>
                <div className="mb-1 text-lg font-medium">테이블 간 데이터 관계 설정을 시작하세요</div>
                <div className="text-sm">
                  <div>왼쪽 사이드바에서 테이블을 더블클릭하여 추가하세요</div>
                  <div className="mt-1 text-xs text-muted-foreground/70">테이블 선택 후 Del 키로 삭제 가능</div>
                </div>
              </div>
            </div>
          )}
        </div>
      </div>

      {/* 연결 설정 모달 */}
      <ConnectionSetupModal
        key={
          pendingConnection
            ? `${pendingConnection.fromNode?.tableName || "unknown"}-${pendingConnection.toNode?.tableName || "unknown"}`
            : "connection-modal"
        }
        isOpen={!!pendingConnection}
        connection={pendingConnection}
        companyCode={companyCode}
        onConfirm={handleConfirmConnection}
        onCancel={handleCancelConnection}
      />

      {/* 엣지 정보 및 액션 버튼 */}
      <EdgeInfoPanel
        isOpen={showEdgeActions}
        edgeInfo={selectedEdgeInfo}
        position={edgeActionPosition}
        onClose={() => {
          setSelectedEdgeInfo(null);
          setShowEdgeActions(false);
          setSelectedEdgeForEdit(null);
          setSelectedColumns({});
        }}
        onEdit={() => {
          if (selectedEdgeInfo) {
            // 기존 관계 찾기
            const existingRelationship = tempRelationships.find((rel) => rel.id === selectedEdgeInfo.relationshipId);

            if (existingRelationship) {
              // 편집 모드로 설정
              setEditingRelationshipId(selectedEdgeInfo.relationshipId);

              // 연결 설정 모달 열기
              const fromTable = nodes.find((node) => node.data?.table?.tableName === selectedEdgeInfo.fromTable);
              const toTable = nodes.find((node) => node.data?.table?.tableName === selectedEdgeInfo.toTable);

              if (fromTable && toTable) {
                setPendingConnection({
                  fromNode: {
                    id: fromTable.id,
                    tableName: selectedEdgeInfo.fromTable,
                    displayName: fromTable.data?.table?.displayName || selectedEdgeInfo.fromTable,
                  },
                  toNode: {
                    id: toTable.id,
                    tableName: selectedEdgeInfo.toTable,
                    displayName: toTable.data?.table?.displayName || selectedEdgeInfo.toTable,
                  },
                  selectedColumnsData: {
                    [selectedEdgeInfo.fromTable]: {
                      displayName: fromTable.data?.table?.displayName || selectedEdgeInfo.fromTable,
                      columns: selectedEdgeInfo.fromColumns || [],
                    },
                    [selectedEdgeInfo.toTable]: {
                      displayName: toTable.data?.table?.displayName || selectedEdgeInfo.toTable,
                      columns: selectedEdgeInfo.toColumns || [],
                    },
                  },
                  existingRelationship: {
                    relationshipName: existingRelationship.relationshipName,
                    connectionType: existingRelationship.connectionType,
                    settings: existingRelationship.settings,
                  },
                });

                // 패널 닫기
                setSelectedEdgeInfo(null);
                setShowEdgeActions(false);
                setSelectedEdgeForEdit(null);
              }
            }
          }
        }}
        onDelete={() => {
          if (selectedEdgeInfo) {
            // 관계 삭제
            setTempRelationships((prev) => prev.filter((rel) => rel.id !== selectedEdgeInfo.relationshipId));

            // 엣지 삭제
            setEdges((prev) => prev.filter((edge) => edge.data?.relationshipId !== selectedEdgeInfo.relationshipId));

            // 변경사항 표시
            setHasUnsavedChanges(true);

            // 패널 닫기
            setSelectedEdgeInfo(null);
            setShowEdgeActions(false);
            setSelectedEdgeForEdit(null);
            setSelectedColumns({});

            toast.success("관계가 삭제되었습니다.");
          }
        }}
      />

      {/* 관계도 저장 모달 */}
      <SaveDiagramModal
        isOpen={showSaveModal}
        onClose={handleCloseSaveModal}
        onSave={handleSaveDiagram}
        relationships={tempRelationships as JsonRelationship[]}
        defaultName={
          diagramId && diagramId > 0 && currentDiagramName
            ? currentDiagramName // 편집 모드: 기존 관계도 이름
            : `관계도 ${new Date().toLocaleDateString()}` // 신규 생성 모드: 새로운 이름
        }
        isLoading={isSaving}
      />
    </div>
  );
};
