"use client";

import { useState, useCallback, useEffect, useMemo, useRef } from "react";
import { Database } from "lucide-react";
import {
  ScreenDefinition,
  ComponentData,
  LayoutData,
  GroupState,
  TableInfo,
  Position,
  ColumnInfo,
  GridSettings,
  ScreenResolution,
  SCREEN_RESOLUTIONS,
} from "@/types/screen";
import { generateComponentId } from "@/lib/utils/generateId";
import { getComponentIdFromWebType } from "@/lib/utils/webTypeMapping";
import {
  createGroupComponent,
  calculateBoundingBox,
  calculateRelativePositions,
  restoreAbsolutePositions,
} from "@/lib/utils/groupingUtils";
import {
  calculateGridInfo,
  snapToGrid,
  snapSizeToGrid,
  generateGridLines,
  updateSizeFromGridColumns,
  adjustGridColumnsFromSize,
  alignGroupChildrenToGrid,
  calculateOptimalGroupSize,
  normalizeGroupChildPositions,
  calculateWidthFromColumns,
  GridSettings as GridUtilSettings,
} from "@/lib/utils/gridUtils";
import { GroupingToolbar } from "./GroupingToolbar";
import { screenApi, tableTypeApi } from "@/lib/api/screen";
import { toast } from "sonner";
import { MenuAssignmentModal } from "./MenuAssignmentModal";
import { initializeComponents } from "@/lib/registry/components";

import StyleEditor from "./StyleEditor";
import { RealtimePreview } from "./RealtimePreviewDynamic";
import FloatingPanel from "./FloatingPanel";
import DesignerToolbar from "./DesignerToolbar";
import TablesPanel from "./panels/TablesPanel";
import { TemplatesPanel, TemplateComponent } from "./panels/TemplatesPanel";
import ComponentsPanel from "./panels/ComponentsPanel";
import LayoutsPanel from "./panels/LayoutsPanel";
import PropertiesPanel from "./panels/PropertiesPanel";
import DetailSettingsPanel from "./panels/DetailSettingsPanel";
import GridPanel from "./panels/GridPanel";
import ResolutionPanel from "./panels/ResolutionPanel";
import { usePanelState, PanelConfig } from "@/hooks/usePanelState";

// 레이아웃 초기화
import "@/lib/registry/layouts";

// 컴포넌트 초기화 (새 시스템)
import "@/lib/registry/components";
// 성능 최적화 도구 초기화 (필요시 사용)
import "@/lib/registry/utils/performanceOptimizer";

interface ScreenDesignerProps {
  selectedScreen: ScreenDefinition | null;
  onBackToList: () => void;
}

// 패널 설정
const panelConfigs: PanelConfig[] = [
  {
    id: "tables",
    title: "테이블 목록",
    defaultPosition: "left",
    defaultWidth: 380,
    defaultHeight: 700, // 테이블 목록은 그대로 유지
    shortcutKey: "t",
  },
  {
    id: "templates",
    title: "템플릿",
    defaultPosition: "left",
    defaultWidth: 380,
    defaultHeight: 700,
    shortcutKey: "m", // template의 m
  },
  {
    id: "layouts",
    title: "레이아웃",
    defaultPosition: "left",
    defaultWidth: 380,
    defaultHeight: 700,
    shortcutKey: "l", // layout의 l
  },
  {
    id: "properties",
    title: "속성 편집",
    defaultPosition: "right",
    defaultWidth: 360,
    defaultHeight: 400, // autoHeight 시작점
    shortcutKey: "p",
  },
  {
    id: "styles",
    title: "스타일 편집",
    defaultPosition: "right",
    defaultWidth: 360,
    defaultHeight: 400, // autoHeight 시작점
    shortcutKey: "s",
  },
  {
    id: "grid",
    title: "격자 설정",
    defaultPosition: "right",
    defaultWidth: 320,
    defaultHeight: 400, // autoHeight 시작점
    shortcutKey: "r", // grid의 r로 변경 (그룹과 겹치지 않음)
  },
  {
    id: "detailSettings",
    title: "상세 설정",
    defaultPosition: "right",
    defaultWidth: 400,
    defaultHeight: 400, // autoHeight 시작점
    shortcutKey: "d",
  },
  {
    id: "resolution",
    title: "해상도 설정",
    defaultPosition: "right",
    defaultWidth: 320,
    defaultHeight: 400,
    shortcutKey: "e", // resolution의 e
  },
];

export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenDesignerProps) {
  // 패널 상태 관리
  const { panelStates, togglePanel, openPanel, closePanel } = usePanelState(panelConfigs);

  const [layout, setLayout] = useState<LayoutData>({
    components: [],
    gridSettings: {
      columns: 12,
      gap: 16,
      padding: 16,
      snapToGrid: true,
      showGrid: true,
      gridColor: "#d1d5db",
      gridOpacity: 0.5,
    },
  });
  const [isSaving, setIsSaving] = useState(false);

  // 메뉴 할당 모달 상태
  const [showMenuAssignmentModal, setShowMenuAssignmentModal] = useState(false);

  // 해상도 설정 상태
  const [screenResolution, setScreenResolution] = useState<ScreenResolution>(
    SCREEN_RESOLUTIONS[0], // 기본값: Full HD
  );

  const [selectedComponent, setSelectedComponent] = useState<ComponentData | null>(null);

  // 클립보드 상태
  const [clipboard, setClipboard] = useState<ComponentData[]>([]);

  // 실행취소/다시실행을 위한 히스토리 상태
  const [history, setHistory] = useState<LayoutData[]>([]);
  const [historyIndex, setHistoryIndex] = useState(-1);

  // 그룹 상태
  const [groupState, setGroupState] = useState<GroupState>({
    selectedComponents: [],
    isGrouping: false,
  });

  // 드래그 상태
  const [dragState, setDragState] = useState({
    isDragging: false,
    draggedComponent: null as ComponentData | null,
    draggedComponents: [] as ComponentData[], // 다중 드래그를 위한 컴포넌트 배열
    originalPosition: { x: 0, y: 0, z: 1 },
    currentPosition: { x: 0, y: 0, z: 1 },
    grabOffset: { x: 0, y: 0 },
    justFinishedDrag: false, // 드래그 종료 직후 클릭 방지용
  });

  // 드래그 선택 상태
  const [selectionDrag, setSelectionDrag] = useState({
    isSelecting: false,
    startPoint: { x: 0, y: 0, z: 1 },
    currentPoint: { x: 0, y: 0, z: 1 },
    wasSelecting: false, // 방금 전에 드래그 선택이 진행 중이었는지 추적
  });

  // 테이블 데이터
  const [tables, setTables] = useState<TableInfo[]>([]);
  const [searchTerm, setSearchTerm] = useState("");

  // 그룹 생성 다이얼로그
  const [showGroupCreateDialog, setShowGroupCreateDialog] = useState(false);

  const canvasRef = useRef<HTMLDivElement>(null);

  // 격자 정보 계산
  const [canvasSize, setCanvasSize] = useState({ width: 0, height: 0 });

  const gridInfo = useMemo(() => {
    if (!layout.gridSettings) return null;

    // 캔버스 크기 계산 (해상도 설정 우선)
    let width = screenResolution.width;
    let height = screenResolution.height;

    // 해상도가 설정되지 않은 경우 기본값 사용
    if (!width || !height) {
      width = canvasSize.width || window.innerWidth - 100;
      height = canvasSize.height || window.innerHeight - 200;
    }

    const newGridInfo = calculateGridInfo(width, height, {
      columns: layout.gridSettings.columns,
      gap: layout.gridSettings.gap,
      padding: layout.gridSettings.padding,
      snapToGrid: layout.gridSettings.snapToGrid || false,
    });

    console.log("🧮 격자 정보 재계산:", {
      resolution: `${width}x${height}`,
      columns: layout.gridSettings.columns,
      gap: layout.gridSettings.gap,
      padding: layout.gridSettings.padding,
      columnWidth: newGridInfo.columnWidth.toFixed(2),
      snapToGrid: layout.gridSettings.snapToGrid,
    });

    return newGridInfo;
  }, [layout.gridSettings, screenResolution]);

  // 격자 라인 생성
  const gridLines = useMemo(() => {
    if (!gridInfo || !layout.gridSettings?.showGrid) return [];

    // 캔버스 크기는 해상도 크기 사용
    const width = screenResolution.width;
    const height = screenResolution.height;

    const lines = generateGridLines(width, height, {
      columns: layout.gridSettings.columns,
      gap: layout.gridSettings.gap,
      padding: layout.gridSettings.padding,
      snapToGrid: layout.gridSettings.snapToGrid || false,
    });

    // 수직선과 수평선을 하나의 배열로 합치기
    const allLines = [
      ...lines.verticalLines.map((pos) => ({ type: "vertical" as const, position: pos })),
      ...lines.horizontalLines.map((pos) => ({ type: "horizontal" as const, position: pos })),
    ];

    return allLines;
  }, [gridInfo, layout.gridSettings, screenResolution]);

  // 필터된 테이블 목록
  const filteredTables = useMemo(() => {
    if (!searchTerm) return tables;
    return tables.filter(
      (table) =>
        table.tableName.toLowerCase().includes(searchTerm.toLowerCase()) ||
        table.columns.some((col) => col.columnName.toLowerCase().includes(searchTerm.toLowerCase())),
    );
  }, [tables, searchTerm]);

  // 히스토리에 저장
  const saveToHistory = useCallback(
    (newLayout: LayoutData) => {
      setHistory((prev) => {
        const newHistory = prev.slice(0, historyIndex + 1);
        newHistory.push(newLayout);
        return newHistory.slice(-50); // 최대 50개까지만 저장
      });
      setHistoryIndex((prev) => Math.min(prev + 1, 49));
    },
    [historyIndex],
  );

  // 실행취소
  const undo = useCallback(() => {
    if (historyIndex > 0) {
      setHistoryIndex((prev) => prev - 1);
      setLayout(history[historyIndex - 1]);
    }
  }, [history, historyIndex]);

  // 다시실행
  const redo = useCallback(() => {
    if (historyIndex < history.length - 1) {
      setHistoryIndex((prev) => prev + 1);
      setLayout(history[historyIndex + 1]);
    }
  }, [history, historyIndex]);

  // 컴포넌트 속성 업데이트
  const updateComponentProperty = useCallback(
    (componentId: string, path: string, value: any) => {
      console.log("⚙️ 컴포넌트 속성 업데이트:", {
        componentId,
        path,
        value,
        timestamp: new Date().toISOString(),
      });

      const targetComponent = layout.components.find((comp) => comp.id === componentId);
      const isLayoutComponent = targetComponent?.type === "layout";

      // 레이아웃 컴포넌트의 위치가 변경되는 경우 존에 속한 컴포넌트들도 함께 이동
      let positionDelta = { x: 0, y: 0 };
      if (isLayoutComponent && (path === "position.x" || path === "position.y" || path === "position")) {
        const oldPosition = targetComponent.position;
        let newPosition = { ...oldPosition };

        if (path === "position.x") {
          newPosition.x = value;
          positionDelta.x = value - oldPosition.x;
        } else if (path === "position.y") {
          newPosition.y = value;
          positionDelta.y = value - oldPosition.y;
        } else if (path === "position") {
          newPosition = value;
          positionDelta.x = value.x - oldPosition.x;
          positionDelta.y = value.y - oldPosition.y;
        }

        console.log("📐 레이아웃 이동 감지:", {
          layoutId: componentId,
          oldPosition,
          newPosition,
          positionDelta,
        });
      }

      const pathParts = path.split(".");
      const updatedComponents = layout.components.map((comp) => {
        if (comp.id !== componentId) {
          // 레이아웃 이동 시 존에 속한 컴포넌트들도 함께 이동
          if (isLayoutComponent && (positionDelta.x !== 0 || positionDelta.y !== 0)) {
            // 이 레이아웃의 존에 속한 컴포넌트인지 확인
            const isInLayoutZone = comp.parentId === componentId && comp.zoneId;
            if (isInLayoutZone) {
              console.log("🔄 존 컴포넌트 함께 이동:", {
                componentId: comp.id,
                zoneId: comp.zoneId,
                oldPosition: comp.position,
                delta: positionDelta,
              });

              return {
                ...comp,
                position: {
                  ...comp.position,
                  x: comp.position.x + positionDelta.x,
                  y: comp.position.y + positionDelta.y,
                },
              };
            }
          }
          return comp;
        }

        const newComp = { ...comp };
        let current: any = newComp;

        for (let i = 0; i < pathParts.length - 1; i++) {
          if (!current[pathParts[i]]) {
            current[pathParts[i]] = {};
          }
          current = current[pathParts[i]];
        }
        current[pathParts[pathParts.length - 1]] = value;

        console.log("✅ 컴포넌트 업데이트 완료:", {
          componentId,
          path,
          newValue: current[pathParts[pathParts.length - 1]],
          fullComponent: newComp,
          webTypeConfig: newComp.type === "widget" ? (newComp as any).webTypeConfig : null,
        });

        // webTypeConfig 업데이트의 경우 추가 검증
        if (path === "webTypeConfig") {
          console.log("🎛️ webTypeConfig 특별 처리:", {
            componentId,
            oldConfig: comp.type === "widget" ? (comp as any).webTypeConfig : null,
            newConfig: current[pathParts[pathParts.length - 1]],
            configType: typeof current[pathParts[pathParts.length - 1]],
            configStringified: JSON.stringify(current[pathParts[pathParts.length - 1]]),
            oldConfigStringified: JSON.stringify(comp.type === "widget" ? (comp as any).webTypeConfig : null),
            isConfigChanged:
              JSON.stringify(comp.type === "widget" ? (comp as any).webTypeConfig : null) !==
              JSON.stringify(current[pathParts[pathParts.length - 1]]),
            timestamp: new Date().toISOString(),
          });
        }

        // gridColumns 변경 시 크기 자동 업데이트
        console.log("🔍 gridColumns 변경 감지:", {
          path,
          value,
          componentType: newComp.type,
          hasGridInfo: !!gridInfo,
          hasGridSettings: !!layout.gridSettings,
          currentGridColumns: (newComp as any).gridColumns,
        });

        if (path === "gridColumns" && gridInfo) {
          const updatedSize = updateSizeFromGridColumns(newComp, gridInfo, layout.gridSettings as GridUtilSettings);
          newComp.size = updatedSize;
          console.log("📏 gridColumns 변경으로 크기 업데이트:", {
            gridColumns: value,
            oldSize: comp.size,
            newSize: updatedSize,
          });
        } else if (path === "gridColumns") {
          console.log("❌ gridColumns 변경 실패:", {
            hasGridInfo: !!gridInfo,
            hasGridSettings: !!layout.gridSettings,
            gridInfo,
            gridSettings: layout.gridSettings,
          });
        }

        // 크기 변경 시 격자 스냅 적용 (그룹 컴포넌트 제외)
        if (
          (path === "size.width" || path === "size.height") &&
          layout.gridSettings?.snapToGrid &&
          gridInfo &&
          newComp.type !== "group"
        ) {
          // 현재 해상도에 맞는 격자 정보로 스냅 적용
          const currentGridInfo = calculateGridInfo(screenResolution.width, screenResolution.height, {
            columns: layout.gridSettings.columns,
            gap: layout.gridSettings.gap,
            padding: layout.gridSettings.padding,
            snapToGrid: layout.gridSettings.snapToGrid || false,
          });
          const snappedSize = snapSizeToGrid(newComp.size, currentGridInfo, layout.gridSettings as GridUtilSettings);
          newComp.size = snappedSize;

          // 크기 변경 시 gridColumns도 자동 조정
          const adjustedColumns = adjustGridColumnsFromSize(
            newComp,
            currentGridInfo,
            layout.gridSettings as GridUtilSettings,
          );
          if (newComp.gridColumns !== adjustedColumns) {
            newComp.gridColumns = adjustedColumns;
            console.log("📏 크기 변경으로 gridColumns 자동 조정:", {
              oldColumns: comp.gridColumns,
              newColumns: adjustedColumns,
              newSize: snappedSize,
            });
          }
        }

        // gridColumns 변경 시 크기를 격자에 맞게 자동 조정
        if (path === "gridColumns" && layout.gridSettings?.snapToGrid && newComp.type !== "group") {
          const currentGridInfo = calculateGridInfo(screenResolution.width, screenResolution.height, {
            columns: layout.gridSettings.columns,
            gap: layout.gridSettings.gap,
            padding: layout.gridSettings.padding,
            snapToGrid: layout.gridSettings.snapToGrid || false,
          });

          // gridColumns에 맞는 정확한 너비 계산
          const newWidth = calculateWidthFromColumns(
            newComp.gridColumns,
            currentGridInfo,
            layout.gridSettings as GridUtilSettings,
          );
          newComp.size = {
            ...newComp.size,
            width: newWidth,
          };

          console.log("📐 gridColumns 변경으로 크기 자동 조정:", {
            componentId,
            gridColumns: newComp.gridColumns,
            oldWidth: comp.size.width,
            newWidth: newWidth,
            columnWidth: currentGridInfo.columnWidth,
            gap: layout.gridSettings.gap,
          });
        }

        // 위치 변경 시 격자 스냅 적용 (그룹 내부 컴포넌트 포함)
        if (
          (path === "position.x" || path === "position.y" || path === "position") &&
          layout.gridSettings?.snapToGrid
        ) {
          // 현재 해상도에 맞는 격자 정보 계산
          const currentGridInfo = calculateGridInfo(screenResolution.width, screenResolution.height, {
            columns: layout.gridSettings.columns,
            gap: layout.gridSettings.gap,
            padding: layout.gridSettings.padding,
            snapToGrid: layout.gridSettings.snapToGrid || false,
          });

          // 그룹 내부 컴포넌트인 경우 패딩을 고려한 격자 스냅 적용
          if (newComp.parentId && currentGridInfo) {
            const { columnWidth } = currentGridInfo;
            const { gap } = layout.gridSettings;

            // 그룹 내부 패딩 고려한 격자 정렬
            const padding = 16;
            const effectiveX = newComp.position.x - padding;
            const columnIndex = Math.round(effectiveX / (columnWidth + (gap || 16)));
            const snappedX = padding + columnIndex * (columnWidth + (gap || 16));

            // Y 좌표는 20px 단위로 스냅
            const effectiveY = newComp.position.y - padding;
            const rowIndex = Math.round(effectiveY / 20);
            const snappedY = padding + rowIndex * 20;

            // 크기도 외부 격자와 동일하게 스냅
            const fullColumnWidth = columnWidth + (gap || 16); // 외부 격자와 동일한 크기
            const widthInColumns = Math.max(1, Math.round(newComp.size.width / fullColumnWidth));
            const snappedWidth = widthInColumns * fullColumnWidth - (gap || 16); // gap 제거하여 실제 컴포넌트 크기
            const snappedHeight = Math.max(40, Math.round(newComp.size.height / 20) * 20);

            newComp.position = {
              x: Math.max(padding, snappedX), // 패딩만큼 최소 여백 확보
              y: Math.max(padding, snappedY),
              z: newComp.position.z || 1,
            };

            newComp.size = {
              width: snappedWidth,
              height: snappedHeight,
            };

            console.log("🎯 그룹 내부 컴포넌트 격자 스냅 (패딩 고려):", {
              componentId,
              parentId: newComp.parentId,
              originalPosition: comp.position,
              originalSize: comp.size,
              calculation: {
                effectiveX,
                effectiveY,
                columnIndex,
                rowIndex,
                columnWidth,
                fullColumnWidth,
                widthInColumns,
                gap: gap || 16,
                padding,
              },
              snappedPosition: newComp.position,
              snappedSize: newComp.size,
            });
          } else if (newComp.type !== "group") {
            // 그룹이 아닌 일반 컴포넌트만 격자 스냅 적용
            const snappedPosition = snapToGrid(
              newComp.position,
              currentGridInfo,
              layout.gridSettings as GridUtilSettings,
            );
            newComp.position = snappedPosition;

            console.log("🧲 일반 컴포넌트 격자 스냅:", {
              componentId,
              originalPosition: comp.position,
              snappedPosition,
            });
          } else {
            console.log("🔓 그룹 컴포넌트는 격자 스냅 제외:", {
              componentId,
              type: newComp.type,
              position: newComp.position,
            });
          }
        }

        return newComp;
      });

      const newLayout = { ...layout, components: updatedComponents };
      setLayout(newLayout);
      saveToHistory(newLayout);

      // selectedComponent가 업데이트된 컴포넌트와 같다면 selectedComponent도 업데이트
      if (selectedComponent && selectedComponent.id === componentId) {
        const updatedSelectedComponent = updatedComponents.find((c) => c.id === componentId);
        if (updatedSelectedComponent) {
          console.log("🔄 selectedComponent 동기화:", {
            componentId,
            path,
            oldColumnsCount:
              selectedComponent.type === "datatable" ? (selectedComponent as any).columns?.length : "N/A",
            newColumnsCount:
              updatedSelectedComponent.type === "datatable" ? (updatedSelectedComponent as any).columns?.length : "N/A",
            oldFiltersCount:
              selectedComponent.type === "datatable" ? (selectedComponent as any).filters?.length : "N/A",
            newFiltersCount:
              updatedSelectedComponent.type === "datatable" ? (updatedSelectedComponent as any).filters?.length : "N/A",
            timestamp: new Date().toISOString(),
          });
          setSelectedComponent(updatedSelectedComponent);
        }
      }

      // webTypeConfig 업데이트 후 레이아웃 상태 확인
      if (path === "webTypeConfig") {
        const updatedComponent = newLayout.components.find((c) => c.id === componentId);
        console.log("🔄 레이아웃 업데이트 후 컴포넌트 상태:", {
          componentId,
          updatedComponent: updatedComponent
            ? {
                id: updatedComponent.id,
                type: updatedComponent.type,
                webTypeConfig: updatedComponent.type === "widget" ? (updatedComponent as any).webTypeConfig : null,
              }
            : null,
          layoutComponentsCount: newLayout.components.length,
          timestamp: new Date().toISOString(),
        });
      }
    },
    [layout, gridInfo, saveToHistory],
  );

  // 컴포넌트 시스템 초기화
  useEffect(() => {
    const initComponents = async () => {
      try {
        console.log("🚀 컴포넌트 시스템 초기화 시작...");
        await initializeComponents();
        console.log("✅ 컴포넌트 시스템 초기화 완료");
      } catch (error) {
        console.error("❌ 컴포넌트 시스템 초기화 실패:", error);
      }
    };

    initComponents();
  }, []);

  // 테이블 데이터 로드 (성능 최적화: 선택된 테이블만 조회)
  useEffect(() => {
    if (selectedScreen?.tableName && selectedScreen.tableName.trim()) {
      const loadTable = async () => {
        try {
          // 선택된 화면의 특정 테이블 정보만 조회 (성능 최적화)
          const [columnsResponse, tableLabelResponse] = await Promise.all([
            tableTypeApi.getColumns(selectedScreen.tableName),
            tableTypeApi.getTableLabel(selectedScreen.tableName),
          ]);

          const columns: ColumnInfo[] = (columnsResponse || []).map((col: any) => ({
            tableName: col.tableName || selectedScreen.tableName,
            columnName: col.columnName || col.column_name,
            // 우선순위: displayName(라벨) > columnLabel > column_label > columnName > column_name
            columnLabel: col.displayName || col.columnLabel || col.column_label || col.columnName || col.column_name,
            dataType: col.dataType || col.data_type || col.dbType,
            webType: col.webType || col.web_type,
            widgetType: col.widgetType || col.widget_type || col.webType || col.web_type,
            isNullable: col.isNullable || col.is_nullable,
            required: col.required !== undefined ? col.required : col.isNullable === "NO" || col.is_nullable === "NO",
            columnDefault: col.columnDefault || col.column_default,
            characterMaximumLength: col.characterMaximumLength || col.character_maximum_length,
          }));

          const tableInfo: TableInfo = {
            tableName: selectedScreen.tableName,
            // 테이블 라벨이 있으면 우선 표시, 없으면 테이블명 그대로
            tableLabel: tableLabelResponse.tableLabel || selectedScreen.tableName,
            columns: columns,
          };
          setTables([tableInfo]); // 단일 테이블 정보만 설정
        } catch (error) {
          console.error("테이블 정보 로드 실패:", error);
          toast.error(`테이블 '${selectedScreen.tableName}' 정보를 불러오는데 실패했습니다.`);
        }
      };

      loadTable();
    } else {
      // 테이블명이 없는 경우 테이블 목록 초기화
      setTables([]);
    }
  }, [selectedScreen?.tableName]);

  // 화면 레이아웃 로드
  useEffect(() => {
    if (selectedScreen?.screenId) {
      const loadLayout = async () => {
        try {
          const response = await screenApi.getLayout(selectedScreen.screenId);
          if (response) {
            // 기본 격자 설정 보장 (격자 표시와 스냅 기본 활성화)
            const layoutWithDefaultGrid = {
              ...response,
              gridSettings: {
                columns: 12,
                gap: 16,
                padding: 16,
                snapToGrid: true,
                showGrid: true,
                gridColor: "#d1d5db",
                gridOpacity: 0.5,
                ...response.gridSettings, // 기존 설정이 있으면 덮어쓰기
              },
            };

            // 저장된 해상도 정보가 있으면 적용, 없으면 기본값 사용
            if (response.screenResolution) {
              setScreenResolution(response.screenResolution);
              console.log("💾 저장된 해상도 불러옴:", response.screenResolution);
            } else {
              // 기본 해상도 (Full HD)
              const defaultResolution =
                SCREEN_RESOLUTIONS.find((r) => r.name === "Full HD (1920×1080)") || SCREEN_RESOLUTIONS[0];
              setScreenResolution(defaultResolution);
              console.log("🔧 기본 해상도 적용:", defaultResolution);
            }

            setLayout(layoutWithDefaultGrid);
            setHistory([layoutWithDefaultGrid]);
            setHistoryIndex(0);
          }
        } catch (error) {
          console.error("레이아웃 로드 실패:", error);
          toast.error("화면 레이아웃을 불러오는데 실패했습니다.");
        }
      };
      loadLayout();
    }
  }, [selectedScreen?.screenId]);

  // 격자 설정 업데이트 및 컴포넌트 자동 스냅
  const updateGridSettings = useCallback(
    (newGridSettings: GridSettings) => {
      const newLayout = { ...layout, gridSettings: newGridSettings };

      // 격자 스냅이 활성화된 경우, 모든 컴포넌트를 새로운 격자에 맞게 조정
      if (newGridSettings.snapToGrid && screenResolution.width > 0) {
        // 새로운 격자 설정으로 격자 정보 재계산 (해상도 기준)
        const newGridInfo = calculateGridInfo(screenResolution.width, screenResolution.height, {
          columns: newGridSettings.columns,
          gap: newGridSettings.gap,
          padding: newGridSettings.padding,
          snapToGrid: newGridSettings.snapToGrid || false,
        });

        const gridUtilSettings = {
          columns: newGridSettings.columns,
          gap: newGridSettings.gap,
          padding: newGridSettings.padding,
          snapToGrid: newGridSettings.snapToGrid,
        };

        const adjustedComponents = layout.components.map((comp) => {
          const snappedPosition = snapToGrid(comp.position, newGridInfo, gridUtilSettings);
          const snappedSize = snapSizeToGrid(comp.size, newGridInfo, gridUtilSettings);

          // gridColumns가 없거나 범위를 벗어나면 자동 조정
          let adjustedGridColumns = comp.gridColumns;
          if (!adjustedGridColumns || adjustedGridColumns < 1 || adjustedGridColumns > newGridSettings.columns) {
            adjustedGridColumns = adjustGridColumnsFromSize({ size: snappedSize }, newGridInfo, gridUtilSettings);
          }

          return {
            ...comp,
            position: snappedPosition,
            size: snappedSize,
            gridColumns: adjustedGridColumns, // gridColumns 속성 추가/조정
          };
        });

        newLayout.components = adjustedComponents;
        console.log("격자 설정 변경으로 컴포넌트 위치 및 크기 자동 조정:", adjustedComponents.length, "개");
        console.log("새로운 격자 정보:", newGridInfo);
      }

      setLayout(newLayout);
      saveToHistory(newLayout);
    },
    [layout, screenResolution, saveToHistory],
  );

  // 해상도 변경 핸들러
  const handleResolutionChange = useCallback(
    (newResolution: ScreenResolution) => {
      console.log("📱 해상도 변경 시작:", {
        from: `${screenResolution.width}x${screenResolution.height}`,
        to: `${newResolution.width}x${newResolution.height}`,
        hasComponents: layout.components.length > 0,
        snapToGrid: layout.gridSettings?.snapToGrid || false,
      });

      setScreenResolution(newResolution);

      // 해상도 변경 시에는 격자 스냅을 적용하지 않고 해상도 정보만 업데이트
      // 이는 기존 컴포넌트들의 위치를 보존하기 위함
      const updatedLayout = {
        ...layout,
        screenResolution: newResolution,
      };

      setLayout(updatedLayout);
      saveToHistory(updatedLayout);

      console.log("✅ 해상도 변경 완료:", {
        newResolution: `${newResolution.width}x${newResolution.height}`,
        preservedComponents: layout.components.length,
        note: "컴포넌트 위치는 보존됨 (격자 스냅 생략)",
      });
    },
    [layout, saveToHistory, screenResolution],
  );

  // 강제 격자 재조정 핸들러 (해상도 변경 후 수동 격자 맞춤용)
  const handleForceGridUpdate = useCallback(() => {
    if (!layout.gridSettings?.snapToGrid || layout.components.length === 0) {
      console.log("격자 재조정 생략: 스냅 비활성화 또는 컴포넌트 없음");
      return;
    }

    console.log("🔄 격자 강제 재조정 시작:", {
      componentsCount: layout.components.length,
      resolution: `${screenResolution.width}x${screenResolution.height}`,
      gridSettings: layout.gridSettings,
    });

    // 현재 해상도로 격자 정보 계산
    const currentGridInfo = calculateGridInfo(screenResolution.width, screenResolution.height, {
      columns: layout.gridSettings.columns,
      gap: layout.gridSettings.gap,
      padding: layout.gridSettings.padding,
      snapToGrid: layout.gridSettings.snapToGrid || false,
    });

    const gridUtilSettings = {
      columns: layout.gridSettings.columns,
      gap: layout.gridSettings.gap,
      padding: layout.gridSettings.padding,
      snapToGrid: layout.gridSettings.snapToGrid,
    };

    const adjustedComponents = layout.components.map((comp) => {
      const snappedPosition = snapToGrid(comp.position, currentGridInfo, gridUtilSettings);
      const snappedSize = snapSizeToGrid(comp.size, currentGridInfo, gridUtilSettings);

      // gridColumns가 없거나 범위를 벗어나면 자동 조정
      let adjustedGridColumns = comp.gridColumns;
      if (!adjustedGridColumns || adjustedGridColumns < 1 || adjustedGridColumns > layout.gridSettings!.columns) {
        adjustedGridColumns = adjustGridColumnsFromSize({ size: snappedSize }, currentGridInfo, gridUtilSettings);
      }

      return {
        ...comp,
        position: snappedPosition,
        size: snappedSize,
        gridColumns: adjustedGridColumns,
      };
    });

    const newLayout = { ...layout, components: adjustedComponents };
    setLayout(newLayout);
    saveToHistory(newLayout);

    console.log("✅ 격자 강제 재조정 완료:", {
      adjustedComponents: adjustedComponents.length,
      gridInfo: {
        columnWidth: currentGridInfo.columnWidth.toFixed(2),
        totalWidth: currentGridInfo.totalWidth,
        columns: layout.gridSettings.columns,
      },
    });

    toast.success(`${adjustedComponents.length}개 컴포넌트가 격자에 맞게 재정렬되었습니다.`);
  }, [layout, screenResolution, saveToHistory]);

  // 저장
  const handleSave = useCallback(async () => {
    if (!selectedScreen?.screenId) return;

    try {
      setIsSaving(true);
      // 해상도 정보를 포함한 레이아웃 데이터 생성
      const layoutWithResolution = {
        ...layout,
        screenResolution: screenResolution,
      };
      console.log("💾 저장할 레이아웃 데이터:", {
        componentsCount: layoutWithResolution.components.length,
        gridSettings: layoutWithResolution.gridSettings,
        screenResolution: layoutWithResolution.screenResolution,
      });
      await screenApi.saveLayout(selectedScreen.screenId, layoutWithResolution);
      toast.success("화면이 저장되었습니다.");

      // 저장 성공 후 메뉴 할당 모달 열기
      setShowMenuAssignmentModal(true);
    } catch (error) {
      console.error("저장 실패:", error);
      toast.error("저장 중 오류가 발생했습니다.");
    } finally {
      setIsSaving(false);
    }
  }, [selectedScreen?.screenId, layout, screenResolution]);

  // 템플릿 드래그 처리
  const handleTemplateDrop = useCallback(
    (e: React.DragEvent, template: TemplateComponent) => {
      const rect = canvasRef.current?.getBoundingClientRect();
      if (!rect) return;

      const dropX = e.clientX - rect.left;
      const dropY = e.clientY - rect.top;

      // 현재 해상도에 맞는 격자 정보 계산
      const currentGridInfo = layout.gridSettings
        ? calculateGridInfo(screenResolution.width, screenResolution.height, {
            columns: layout.gridSettings.columns,
            gap: layout.gridSettings.gap,
            padding: layout.gridSettings.padding,
            snapToGrid: layout.gridSettings.snapToGrid || false,
          })
        : null;

      // 격자 스냅 적용
      const snappedPosition =
        layout.gridSettings?.snapToGrid && currentGridInfo
          ? snapToGrid({ x: dropX, y: dropY, z: 1 }, currentGridInfo, layout.gridSettings as GridUtilSettings)
          : { x: dropX, y: dropY, z: 1 };

      console.log("🎨 템플릿 드롭:", {
        templateName: template.name,
        componentsCount: template.components.length,
        dropPosition: { x: dropX, y: dropY },
        snappedPosition,
      });

      // 템플릿의 모든 컴포넌트들을 생성
      // 먼저 ID 매핑을 생성 (parentId 참조를 위해)
      const idMapping: Record<string, string> = {};
      template.components.forEach((templateComp, index) => {
        const newId = generateComponentId();
        if (index === 0) {
          // 첫 번째 컴포넌트(컨테이너)는 "form-container"로 매핑
          idMapping["form-container"] = newId;
        }
        idMapping[templateComp.parentId || `temp_${index}`] = newId;
      });

      const newComponents: ComponentData[] = template.components.map((templateComp, index) => {
        const componentId = index === 0 ? idMapping["form-container"] : generateComponentId();

        // 템플릿 컴포넌트의 상대 위치를 드롭 위치 기준으로 조정
        const absoluteX = snappedPosition.x + templateComp.position.x;
        const absoluteY = snappedPosition.y + templateComp.position.y;

        // 격자 스냅 적용
        const finalPosition =
          layout.gridSettings?.snapToGrid && currentGridInfo
            ? snapToGrid({ x: absoluteX, y: absoluteY, z: 1 }, currentGridInfo, layout.gridSettings as GridUtilSettings)
            : { x: absoluteX, y: absoluteY, z: 1 };

        if (templateComp.type === "container") {
          // 그리드 컬럼 기반 크기 계산
          const gridColumns =
            typeof templateComp.size.width === "number" && templateComp.size.width <= 12 ? templateComp.size.width : 4; // 기본 4컬럼

          const calculatedSize =
            currentGridInfo && layout.gridSettings?.snapToGrid
              ? (() => {
                  const newWidth = calculateWidthFromColumns(
                    gridColumns,
                    currentGridInfo,
                    layout.gridSettings as GridUtilSettings,
                  );
                  return {
                    width: newWidth,
                    height: templateComp.size.height,
                  };
                })()
              : { width: 400, height: templateComp.size.height }; // 폴백 크기

          return {
            id: componentId,
            type: "container",
            label: templateComp.label,
            tableName: selectedScreen?.tableName || "",
            title: templateComp.title || templateComp.label,
            position: finalPosition,
            size: calculatedSize,
            gridColumns,
            style: {
              labelDisplay: true,
              labelFontSize: "14px",
              labelColor: "#374151",
              labelFontWeight: "600",
              labelMarginBottom: "8px",
              ...templateComp.style,
            },
          };
        } else if (templateComp.type === "datatable") {
          // 데이터 테이블 컴포넌트 생성
          const gridColumns = 6; // 기본값: 6컬럼 (50% 너비)

          // gridColumns에 맞는 크기 계산
          const calculatedSize =
            currentGridInfo && layout.gridSettings?.snapToGrid
              ? (() => {
                  const newWidth = calculateWidthFromColumns(
                    gridColumns,
                    currentGridInfo,
                    layout.gridSettings as GridUtilSettings,
                  );
                  return {
                    width: newWidth,
                    height: templateComp.size.height, // 높이는 템플릿 값 유지
                  };
                })()
              : templateComp.size;

          console.log("📊 데이터 테이블 생성 시 크기 계산:", {
            gridColumns,
            templateSize: templateComp.size,
            calculatedSize,
            hasGridInfo: !!currentGridInfo,
            hasGridSettings: !!layout.gridSettings?.snapToGrid,
          });

          return {
            id: componentId,
            type: "datatable",
            label: templateComp.label,
            tableName: selectedScreen?.tableName || "",
            position: finalPosition,
            size: calculatedSize,
            title: templateComp.label,
            columns: [], // 초기에는 빈 배열, 나중에 설정
            filters: [], // 초기에는 빈 배열, 나중에 설정
            pagination: {
              enabled: true,
              pageSize: 10,
              pageSizeOptions: [5, 10, 20, 50],
              showPageSizeSelector: true,
              showPageInfo: true,
              showFirstLast: true,
            },
            showSearchButton: true,
            searchButtonText: "검색",
            enableExport: true,
            enableRefresh: true,
            enableAdd: true,
            enableEdit: true,
            enableDelete: true,
            addButtonText: "추가",
            editButtonText: "수정",
            deleteButtonText: "삭제",
            addModalConfig: {
              title: "새 데이터 추가",
              description: `${templateComp.label}에 새로운 데이터를 추가합니다.`,
              width: "lg",
              layout: "two-column",
              gridColumns: 2,
              fieldOrder: [], // 초기에는 빈 배열, 나중에 컬럼 추가 시 설정
              requiredFields: [],
              hiddenFields: [],
              advancedFieldConfigs: {}, // 초기에는 빈 객체, 나중에 컬럼별 설정
              submitButtonText: "추가",
              cancelButtonText: "취소",
            },
            gridColumns,
            style: {
              labelDisplay: true,
              labelFontSize: "14px",
              labelColor: "#374151",
              labelFontWeight: "600",
              labelMarginBottom: "8px",
              ...templateComp.style,
            },
          } as ComponentData;
        } else if (templateComp.type === "file") {
          // 파일 첨부 컴포넌트 생성
          const gridColumns = 6; // 기본값: 6컬럼

          const calculatedSize =
            currentGridInfo && layout.gridSettings?.snapToGrid
              ? (() => {
                  const newWidth = calculateWidthFromColumns(
                    gridColumns,
                    currentGridInfo,
                    layout.gridSettings as GridUtilSettings,
                  );
                  return {
                    width: newWidth,
                    height: templateComp.size.height,
                  };
                })()
              : templateComp.size;

          return {
            id: componentId,
            type: "file",
            label: templateComp.label,
            position: finalPosition,
            size: calculatedSize,
            gridColumns,
            fileConfig: {
              accept: ["image/*", ".pdf", ".doc", ".docx", ".xls", ".xlsx"],
              multiple: true,
              maxSize: 10, // 10MB
              maxFiles: 5,
              docType: "DOCUMENT",
              docTypeName: "일반 문서",
              targetObjid: selectedScreen?.screenId || "",
              showPreview: true,
              showProgress: true,
              dragDropText: "파일을 드래그하여 업로드하세요",
              uploadButtonText: "파일 선택",
              autoUpload: true,
              chunkedUpload: false,
            },
            uploadedFiles: [],
            style: {
              labelDisplay: true,
              labelFontSize: "14px",
              labelColor: "#374151",
              labelFontWeight: "600",
              labelMarginBottom: "8px",
              ...templateComp.style,
            },
          } as ComponentData;
        } else if (templateComp.type === "area") {
          // 영역 컴포넌트 생성
          const gridColumns = 6; // 기본값: 6컬럼 (50% 너비)

          const calculatedSize =
            currentGridInfo && layout.gridSettings?.snapToGrid
              ? (() => {
                  const newWidth = calculateWidthFromColumns(
                    gridColumns,
                    currentGridInfo,
                    layout.gridSettings as GridUtilSettings,
                  );
                  return {
                    width: newWidth,
                    height: templateComp.size.height,
                  };
                })()
              : templateComp.size;

          return {
            id: componentId,
            type: "area",
            label: templateComp.label,
            position: finalPosition,
            size: calculatedSize,
            gridColumns,
            layoutType: (templateComp as any).layoutType || "box",
            title: (templateComp as any).title || templateComp.label,
            description: (templateComp as any).description,
            layoutConfig: (templateComp as any).layoutConfig || {},
            areaStyle: {
              backgroundColor: "#ffffff",
              borderWidth: 1,
              borderStyle: "solid",
              borderColor: "#e5e7eb",
              borderRadius: 8,
              padding: 16,
              margin: 0,
              shadow: "sm",
              ...(templateComp as any).areaStyle,
            },
            children: [],
            style: {
              labelDisplay: true,
              labelFontSize: "14px",
              labelColor: "#374151",
              labelFontWeight: "600",
              labelMarginBottom: "8px",
              ...templateComp.style,
            },
          } as ComponentData;
        } else {
          // 위젯 컴포넌트
          const widgetType = templateComp.widgetType || "text";

          // 웹타입별 기본 설정 생성
          const getDefaultWebTypeConfig = (wType: string) => {
            switch (wType) {
              case "date":
                return {
                  format: "YYYY-MM-DD" as const,
                  showTime: false,
                  placeholder: templateComp.placeholder || "날짜를 선택하세요",
                };
              case "select":
              case "dropdown":
                return {
                  options: [
                    { label: "옵션 1", value: "option1" },
                    { label: "옵션 2", value: "option2" },
                    { label: "옵션 3", value: "option3" },
                  ],
                  multiple: false,
                  searchable: false,
                  placeholder: templateComp.placeholder || "옵션을 선택하세요",
                };
              case "text":
                return {
                  format: "none" as const,
                  placeholder: templateComp.placeholder || "텍스트를 입력하세요",
                  multiline: false,
                };
              case "email":
                return {
                  format: "email" as const,
                  placeholder: templateComp.placeholder || "이메일을 입력하세요",
                  multiline: false,
                };
              case "tel":
                return {
                  format: "phone" as const,
                  placeholder: templateComp.placeholder || "전화번호를 입력하세요",
                  multiline: false,
                };
              case "textarea":
                return {
                  rows: 3,
                  placeholder: templateComp.placeholder || "텍스트를 입력하세요",
                  resizable: true,
                  wordWrap: true,
                };
              default:
                return {
                  placeholder: templateComp.placeholder || "입력하세요",
                };
            }
          };

          // 위젯 크기도 격자에 맞게 조정
          const widgetSize =
            currentGridInfo && layout.gridSettings?.snapToGrid
              ? {
                  width: calculateWidthFromColumns(1, currentGridInfo, layout.gridSettings as GridUtilSettings),
                  height: templateComp.size.height,
                }
              : templateComp.size;

          return {
            id: componentId,
            type: "widget",
            widgetType: widgetType as any,
            label: templateComp.label,
            placeholder: templateComp.placeholder,
            columnName: `field_${index + 1}`,
            parentId: templateComp.parentId ? idMapping[templateComp.parentId] : undefined,
            position: finalPosition,
            size: widgetSize,
            required: templateComp.required || false,
            readonly: templateComp.readonly || false,
            gridColumns: 1,
            webTypeConfig: getDefaultWebTypeConfig(widgetType),
            style: {
              labelDisplay: true,
              labelFontSize: "14px",
              labelColor: "#374151",
              labelFontWeight: "600",
              labelMarginBottom: "8px",
              ...templateComp.style,
            },
          } as ComponentData;
        }
      });

      // 레이아웃에 새 컴포넌트들 추가
      const newLayout = {
        ...layout,
        components: [...layout.components, ...newComponents],
      };

      setLayout(newLayout);
      saveToHistory(newLayout);

      // 첫 번째 컴포넌트 선택
      if (newComponents.length > 0) {
        setSelectedComponent(newComponents[0]);
        openPanel("properties");
      }

      toast.success(`${template.name} 템플릿이 추가되었습니다.`);
    },
    [layout, gridInfo, selectedScreen, snapToGrid, saveToHistory, openPanel],
  );

  // 레이아웃 드래그 처리
  const handleLayoutDrop = useCallback(
    (e: React.DragEvent, layoutData: any) => {
      const rect = canvasRef.current?.getBoundingClientRect();
      if (!rect) return;

      const dropX = e.clientX - rect.left;
      const dropY = e.clientY - rect.top;

      // 현재 해상도에 맞는 격자 정보 계산
      const currentGridInfo = layout.gridSettings
        ? calculateGridInfo(screenResolution.width, screenResolution.height, {
            columns: layout.gridSettings.columns,
            gap: layout.gridSettings.gap,
            padding: layout.gridSettings.padding,
            snapToGrid: layout.gridSettings.snapToGrid || false,
          })
        : null;

      // 격자 스냅 적용
      const snappedPosition =
        layout.gridSettings?.snapToGrid && currentGridInfo
          ? snapToGrid({ x: dropX, y: dropY, z: 1 }, currentGridInfo, layout.gridSettings as GridUtilSettings)
          : { x: dropX, y: dropY, z: 1 };

      console.log("🏗️ 레이아웃 드롭:", {
        layoutType: layoutData.layoutType,
        zonesCount: layoutData.zones.length,
        dropPosition: { x: dropX, y: dropY },
        snappedPosition,
      });

      // 레이아웃 컴포넌트 생성
      const newLayoutComponent: ComponentData = {
        id: layoutData.id,
        type: "layout",
        layoutType: layoutData.layoutType,
        layoutConfig: layoutData.layoutConfig,
        zones: layoutData.zones.map((zone: any) => ({
          ...zone,
          id: `${layoutData.id}_${zone.id}`, // 레이아웃 ID를 접두사로 추가
        })),
        children: [],
        position: snappedPosition,
        size: layoutData.size,
        label: layoutData.label,
        allowedComponentTypes: layoutData.allowedComponentTypes,
        dropZoneConfig: layoutData.dropZoneConfig,
      } as ComponentData;

      // 레이아웃에 새 컴포넌트 추가
      const newLayout = {
        ...layout,
        components: [...layout.components, newLayoutComponent],
      };

      setLayout(newLayout);
      saveToHistory(newLayout);

      // 레이아웃 컴포넌트 선택
      setSelectedComponent(newLayoutComponent);
      openPanel("properties");

      toast.success(`${layoutData.label} 레이아웃이 추가되었습니다.`);
    },
    [layout, gridInfo, screenResolution, snapToGrid, saveToHistory, openPanel],
  );

  // handleZoneComponentDrop은 handleComponentDrop으로 대체됨

  // 존 클릭 핸들러
  const handleZoneClick = useCallback((zoneId: string) => {
    console.log("🎯 존 클릭:", zoneId);
    // 필요시 존 선택 로직 추가
  }, []);

  // 웹타입별 기본 설정 생성 함수를 상위로 이동
  const getDefaultWebTypeConfig = useCallback((webType: string) => {
    switch (webType) {
      case "button":
        return {
          actionType: "custom",
          variant: "default",
          confirmationMessage: "",
          popupTitle: "",
          popupContent: "",
          navigateUrl: "",
        };
      case "date":
        return {
          format: "YYYY-MM-DD",
          showTime: false,
          placeholder: "날짜를 선택하세요",
        };
      case "number":
        return {
          format: "integer",
          placeholder: "숫자를 입력하세요",
        };
      case "select":
        return {
          options: [
            { label: "옵션 1", value: "option1" },
            { label: "옵션 2", value: "option2" },
            { label: "옵션 3", value: "option3" },
          ],
          multiple: false,
          searchable: false,
          placeholder: "옵션을 선택하세요",
        };
      case "file":
        return {
          accept: ["*/*"],
          maxSize: 10485760, // 10MB
          multiple: false,
          showPreview: true,
          autoUpload: false,
        };
      default:
        return {};
    }
  }, []);

  // 컴포넌트 드래그 처리 (캔버스 레벨 드롭)
  const handleComponentDrop = useCallback(
    (e: React.DragEvent, component?: any, zoneId?: string, layoutId?: string) => {
      // 존별 드롭인 경우 dragData에서 컴포넌트 정보 추출
      if (!component) {
        const dragData = e.dataTransfer.getData("application/json");
        if (!dragData) return;

        try {
          const parsedData = JSON.parse(dragData);
          if (parsedData.type === "component") {
            component = parsedData.component;
          } else {
            return;
          }
        } catch (error) {
          console.error("드래그 데이터 파싱 오류:", error);
          return;
        }
      }
      const rect = canvasRef.current?.getBoundingClientRect();
      if (!rect) return;

      // 컴포넌트 크기 정보
      const componentWidth = component.defaultSize?.width || 120;
      const componentHeight = component.defaultSize?.height || 36;

      // 방법 1: 마우스 포인터를 컴포넌트 중심으로 (현재 방식)
      const dropX_centered = e.clientX - rect.left - componentWidth / 2;
      const dropY_centered = e.clientY - rect.top - componentHeight / 2;

      // 방법 2: 마우스 포인터를 컴포넌트 좌상단으로 (사용자가 원할 수도 있는 방식)
      const dropX_topleft = e.clientX - rect.left;
      const dropY_topleft = e.clientY - rect.top;

      // 사용자가 원하는 방식으로 변경: 마우스 포인터가 좌상단에 오도록
      const dropX = dropX_topleft;
      const dropY = dropY_topleft;

      console.log("🎯 위치 계산 디버깅:", {
        "1. 마우스 위치": { clientX: e.clientX, clientY: e.clientY },
        "2. 캔버스 위치": { left: rect.left, top: rect.top, width: rect.width, height: rect.height },
        "3. 캔버스 내 상대 위치": { x: e.clientX - rect.left, y: e.clientY - rect.top },
        "4. 컴포넌트 크기": { width: componentWidth, height: componentHeight },
        "5a. 중심 방식 좌상단": { x: dropX_centered, y: dropY_centered },
        "5b. 좌상단 방식": { x: dropX_topleft, y: dropY_topleft },
        "6. 선택된 방식": { dropX, dropY },
        "7. 예상 컴포넌트 중심": { x: dropX + componentWidth / 2, y: dropY + componentHeight / 2 },
        "8. 마우스와 중심 일치 확인": {
          match:
            Math.abs(dropX + componentWidth / 2 - (e.clientX - rect.left)) < 1 &&
            Math.abs(dropY + componentHeight / 2 - (e.clientY - rect.top)) < 1,
        },
      });

      // 현재 해상도에 맞는 격자 정보 계산
      const currentGridInfo = layout.gridSettings
        ? calculateGridInfo(screenResolution.width, screenResolution.height, {
            columns: layout.gridSettings.columns,
            gap: layout.gridSettings.gap,
            padding: layout.gridSettings.padding,
            snapToGrid: layout.gridSettings.snapToGrid || false,
          })
        : null;

      // 캔버스 경계 내로 위치 제한
      const boundedX = Math.max(0, Math.min(dropX, screenResolution.width - componentWidth));
      const boundedY = Math.max(0, Math.min(dropY, screenResolution.height - componentHeight));

      // 격자 스냅 적용
      const snappedPosition =
        layout.gridSettings?.snapToGrid && currentGridInfo
          ? snapToGrid({ x: boundedX, y: boundedY, z: 1 }, currentGridInfo, layout.gridSettings as GridUtilSettings)
          : { x: boundedX, y: boundedY, z: 1 };

      console.log("🧩 컴포넌트 드롭:", {
        componentName: component.name,
        webType: component.webType,
        rawPosition: { x: dropX, y: dropY },
        boundedPosition: { x: boundedX, y: boundedY },
        snappedPosition,
      });

      // 새 컴포넌트 생성 (새 컴포넌트 시스템 지원)
      console.log("🔍 ScreenDesigner handleComponentDrop:", {
        componentName: component.name,
        componentId: component.id,
        webType: component.webType,
        category: component.category,
        defaultConfig: component.defaultConfig,
      });

      const newComponent: ComponentData = {
        id: generateComponentId(),
        type: "component", // ✅ 새 컴포넌트 시스템 사용
        label: component.name,
        widgetType: component.webType,
        componentType: component.id, // 새 컴포넌트 시스템의 ID (DynamicComponentRenderer용)
        position: snappedPosition,
        size: component.defaultSize,
        componentConfig: {
          type: component.id, // 새 컴포넌트 시스템의 ID 사용
          webType: component.webType, // 웹타입 정보 추가
          ...component.defaultConfig,
        },
        webTypeConfig: getDefaultWebTypeConfig(component.webType),
        style: {
          labelDisplay: component.id === "text-display" ? false : true, // 텍스트 표시 컴포넌트는 기본적으로 라벨 숨김
          labelFontSize: "14px",
          labelColor: "#374151",
          labelFontWeight: "500",
          labelMarginBottom: "4px",
        },
      };

      // 레이아웃에 컴포넌트 추가
      const newLayout: LayoutData = {
        ...layout,
        components: [...layout.components, newComponent],
      };

      setLayout(newLayout);
      saveToHistory(newLayout);

      // 새 컴포넌트 선택
      setSelectedComponent(newComponent);
      openPanel("properties");

      toast.success(`${component.name} 컴포넌트가 추가되었습니다.`);
    },
    [layout, gridInfo, selectedScreen, snapToGrid, saveToHistory, openPanel],
  );

  // 드래그 앤 드롭 처리
  const handleDragOver = useCallback((e: React.DragEvent) => {
    e.preventDefault();
  }, []);

  const handleDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();

      const dragData = e.dataTransfer.getData("application/json");
      console.log("🎯 드롭 이벤트:", { dragData });
      if (!dragData) {
        console.log("❌ 드래그 데이터가 없습니다");
        return;
      }

      try {
        const parsedData = JSON.parse(dragData);
        console.log("📋 파싱된 데이터:", parsedData);

        // 템플릿 드래그인 경우
        if (parsedData.type === "template") {
          handleTemplateDrop(e, parsedData.template);
          return;
        }

        // 레이아웃 드래그인 경우
        if (parsedData.type === "layout") {
          handleLayoutDrop(e, parsedData.layout);
          return;
        }

        // 컴포넌트 드래그인 경우
        if (parsedData.type === "component") {
          handleComponentDrop(e, parsedData.component);
          return;
        }

        // 기존 테이블/컬럼 드래그 처리
        const { type, table, column } = parsedData;

        // 드롭 대상이 폼 컨테이너인지 확인
        const dropTarget = e.target as HTMLElement;
        const formContainer = dropTarget.closest('[data-form-container="true"]');

        const rect = canvasRef.current?.getBoundingClientRect();
        if (!rect) return;

        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;

        let newComponent: ComponentData;

        if (type === "table") {
          // 테이블 컨테이너 생성
          newComponent = {
            id: generateComponentId(),
            type: "container",
            label: table.tableLabel || table.tableName, // 테이블 라벨 우선, 없으면 테이블명
            tableName: table.tableName,
            position: { x, y, z: 1 } as Position,
            size: { width: 300, height: 200 },
            style: {
              labelDisplay: true,
              labelFontSize: "14px",
              labelColor: "#374151",
              labelFontWeight: "600",
              labelMarginBottom: "8px",
            },
          };
        } else if (type === "column") {
          console.log("🔄 컬럼 드롭 처리:", { webType: column.widgetType, columnName: column.columnName });
          // 현재 해상도에 맞는 격자 정보로 기본 크기 계산
          const currentGridInfo = layout.gridSettings
            ? calculateGridInfo(screenResolution.width, screenResolution.height, {
                columns: layout.gridSettings.columns,
                gap: layout.gridSettings.gap,
                padding: layout.gridSettings.padding,
                snapToGrid: layout.gridSettings.snapToGrid || false,
              })
            : null;

          // 격자 스냅이 활성화된 경우 정확한 격자 크기로 생성, 아니면 기본값
          const defaultWidth =
            currentGridInfo && layout.gridSettings?.snapToGrid
              ? calculateWidthFromColumns(1, currentGridInfo, layout.gridSettings as GridUtilSettings)
              : 200;

          console.log("🎯 컴포넌트 생성 시 크기 계산:", {
            screenResolution: `${screenResolution.width}x${screenResolution.height}`,
            gridSettings: layout.gridSettings,
            currentGridInfo: currentGridInfo
              ? {
                  columnWidth: currentGridInfo.columnWidth.toFixed(2),
                  totalWidth: currentGridInfo.totalWidth,
                }
              : null,
            defaultWidth: defaultWidth.toFixed(2),
            snapToGrid: layout.gridSettings?.snapToGrid,
          });

          // 웹타입별 기본 설정 생성
          const getDefaultWebTypeConfig = (widgetType: string) => {
            switch (widgetType) {
              case "date":
                return {
                  format: "YYYY-MM-DD" as const,
                  showTime: false,
                  placeholder: "날짜를 선택하세요",
                };
              case "datetime":
                return {
                  format: "YYYY-MM-DD HH:mm" as const,
                  showTime: true,
                  placeholder: "날짜와 시간을 선택하세요",
                };
              case "number":
                return {
                  format: "integer" as const,
                  placeholder: "숫자를 입력하세요",
                };
              case "decimal":
                return {
                  format: "decimal" as const,
                  step: 0.01,
                  decimalPlaces: 2,
                  placeholder: "소수를 입력하세요",
                };
              case "select":
              case "dropdown":
                return {
                  options: [
                    { label: "옵션 1", value: "option1" },
                    { label: "옵션 2", value: "option2" },
                    { label: "옵션 3", value: "option3" },
                  ],
                  multiple: false,
                  searchable: false,
                  placeholder: "옵션을 선택하세요",
                };
              case "text":
                return {
                  format: "none" as const,
                  placeholder: "텍스트를 입력하세요",
                  multiline: false,
                };
              case "email":
                return {
                  format: "email" as const,
                  placeholder: "이메일을 입력하세요",
                  multiline: false,
                };
              case "tel":
                return {
                  format: "phone" as const,
                  placeholder: "전화번호를 입력하세요",
                  multiline: false,
                };
              case "textarea":
                return {
                  rows: 3,
                  placeholder: "텍스트를 입력하세요",
                  resizable: true,
                  autoResize: false,
                  wordWrap: true,
                };
              case "checkbox":
              case "boolean":
                return {
                  defaultChecked: false,
                  labelPosition: "right" as const,
                  checkboxText: "",
                  trueValue: true,
                  falseValue: false,
                  indeterminate: false,
                };
              case "radio":
                return {
                  options: [
                    { label: "옵션 1", value: "option1" },
                    { label: "옵션 2", value: "option2" },
                  ],
                  layout: "vertical" as const,
                  defaultValue: "",
                  allowNone: false,
                };
              case "file":
                return {
                  accept: "",
                  multiple: false,
                  maxSize: 10,
                  maxFiles: 1,
                  preview: true,
                  dragDrop: true,
                  allowedExtensions: [],
                };
              case "code":
                return {
                  language: "javascript",
                  theme: "light",
                  fontSize: 14,
                  lineNumbers: true,
                  wordWrap: false,
                  readOnly: false,
                  autoFormat: true,
                  placeholder: "코드를 입력하세요...",
                };
              case "entity":
                return {
                  entityName: "",
                  displayField: "name",
                  valueField: "id",
                  searchable: true,
                  multiple: false,
                  allowClear: true,
                  placeholder: "엔터티를 선택하세요",
                  apiEndpoint: "",
                  filters: [],
                  displayFormat: "simple" as const,
                };
              default:
                return undefined;
            }
          };

          // 폼 컨테이너에 드롭한 경우
          if (formContainer) {
            const formContainerId = formContainer.getAttribute("data-component-id");
            const formContainerComponent = layout.components.find((c) => c.id === formContainerId);

            if (formContainerComponent) {
              // 폼 내부에서의 상대적 위치 계산
              const containerRect = formContainer.getBoundingClientRect();
              const relativeX = e.clientX - containerRect.left;
              const relativeY = e.clientY - containerRect.top;

              // 웹타입을 새로운 컴포넌트 ID로 매핑
              const componentId = getComponentIdFromWebType(column.widgetType);
              console.log(`🔄 폼 컨테이너 드롭: ${column.widgetType} → ${componentId}`);

              newComponent = {
                id: generateComponentId(),
                type: "component", // ✅ 새로운 컴포넌트 시스템 사용
                label: column.columnLabel || column.columnName,
                tableName: table.tableName,
                columnName: column.columnName,
                required: column.required,
                readonly: false,
                parentId: formContainerId, // 폼 컨테이너의 자식으로 설정
                position: { x: relativeX, y: relativeY, z: 1 } as Position,
                size: { width: defaultWidth, height: 40 },
                gridColumns: 1,
                style: {
                  labelDisplay: true,
                  labelFontSize: "12px",
                  labelColor: "#374151",
                  labelFontWeight: "500",
                  labelMarginBottom: "6px",
                },
                componentConfig: {
                  type: componentId, // text-input, number-input 등
                  webType: column.widgetType, // 원본 웹타입 보존
                  ...getDefaultWebTypeConfig(column.widgetType),
                },
              };
            } else {
              return; // 폼 컨테이너를 찾을 수 없으면 드롭 취소
            }
          } else {
            // 일반 캔버스에 드롭한 경우 - 새로운 컴포넌트 시스템 사용
            const componentId = getComponentIdFromWebType(column.widgetType);
            console.log(`🔄 캔버스 드롭: ${column.widgetType} → ${componentId}`);

            newComponent = {
              id: generateComponentId(),
              type: "component", // ✅ 새로운 컴포넌트 시스템 사용
              label: column.columnLabel || column.columnName, // 컬럼 라벨 우선, 없으면 컬럼명
              tableName: table.tableName,
              columnName: column.columnName,
              required: column.required,
              readonly: false,
              position: { x, y, z: 1 } as Position,
              size: { width: defaultWidth, height: 40 },
              gridColumns: 1,
              style: {
                labelDisplay: true,
                labelFontSize: "12px",
                labelColor: "#374151",
                labelFontWeight: "500",
                labelMarginBottom: "6px",
              },
              componentConfig: {
                type: componentId, // text-input, number-input 등
                webType: column.widgetType, // 원본 웹타입 보존
                ...getDefaultWebTypeConfig(column.widgetType),
              },
            };
          }
        } else {
          return;
        }

        // 격자 스냅 적용 (그룹 컴포넌트 제외)
        if (layout.gridSettings?.snapToGrid && newComponent.type !== "group") {
          // 현재 해상도에 맞는 격자 정보 계산
          const currentGridInfo = calculateGridInfo(screenResolution.width, screenResolution.height, {
            columns: layout.gridSettings.columns,
            gap: layout.gridSettings.gap,
            padding: layout.gridSettings.padding,
            snapToGrid: layout.gridSettings.snapToGrid || false,
          });

          const gridUtilSettings = {
            columns: layout.gridSettings.columns,
            gap: layout.gridSettings.gap,
            padding: layout.gridSettings.padding,
            snapToGrid: layout.gridSettings.snapToGrid || false,
          };
          newComponent.position = snapToGrid(newComponent.position, currentGridInfo, gridUtilSettings);
          newComponent.size = snapSizeToGrid(newComponent.size, currentGridInfo, gridUtilSettings);

          console.log("🧲 새 컴포넌트 격자 스냅 적용:", {
            type: newComponent.type,
            resolution: `${screenResolution.width}x${screenResolution.height}`,
            snappedPosition: newComponent.position,
            snappedSize: newComponent.size,
            columnWidth: currentGridInfo.columnWidth,
          });
        }

        if (newComponent.type === "group") {
          console.log("🔓 그룹 컴포넌트는 격자 스냅 제외:", {
            type: newComponent.type,
            position: newComponent.position,
            size: newComponent.size,
          });
        }

        const newLayout = {
          ...layout,
          components: [...layout.components, newComponent],
        };

        setLayout(newLayout);
        saveToHistory(newLayout);
        setSelectedComponent(newComponent);

        // 속성 패널 자동 열기
        openPanel("properties");
      } catch (error) {
        console.error("드롭 처리 실패:", error);
      }
    },
    [layout, gridInfo, saveToHistory, openPanel],
  );

  // 컴포넌트 클릭 처리 (다중선택 지원)
  const handleComponentClick = useCallback(
    (component: ComponentData, event?: React.MouseEvent) => {
      event?.stopPropagation();

      // 드래그가 끝난 직후라면 클릭을 무시 (다중 선택 유지)
      if (dragState.justFinishedDrag) {
        return;
      }

      const isShiftPressed = event?.shiftKey || false;
      const isCtrlPressed = event?.ctrlKey || event?.metaKey || false;
      const isGroupContainer = component.type === "group";

      if (isShiftPressed || isCtrlPressed || groupState.isGrouping) {
        // 다중 선택 모드
        if (isGroupContainer) {
          // 그룹 컨테이너는 단일 선택으로 처리
          setSelectedComponent(component);
          setGroupState((prev) => ({
            ...prev,
            selectedComponents: [component.id],
            isGrouping: false,
          }));
          return;
        }

        const isSelected = groupState.selectedComponents.includes(component.id);
        setGroupState((prev) => ({
          ...prev,
          selectedComponents: isSelected
            ? prev.selectedComponents.filter((id) => id !== component.id)
            : [...prev.selectedComponents, component.id],
        }));

        // 마지막 선택된 컴포넌트를 selectedComponent로 설정
        if (!isSelected) {
          console.log("🎯 컴포넌트 선택 (다중 모드):", {
            componentId: component.id,
            componentType: component.type,
            webTypeConfig: component.type === "widget" ? (component as any).webTypeConfig : null,
            timestamp: new Date().toISOString(),
          });
          setSelectedComponent(component);
        }
      } else {
        // 단일 선택 모드
        console.log("🎯 컴포넌트 선택 (단일 모드):", {
          componentId: component.id,
          componentType: component.type,
          webTypeConfig: component.type === "widget" ? (component as any).webTypeConfig : null,
          timestamp: new Date().toISOString(),
        });
        setSelectedComponent(component);
        setGroupState((prev) => ({
          ...prev,
          selectedComponents: [component.id],
        }));
      }

      // 속성 패널 자동 열기
      openPanel("properties");
    },
    [openPanel, groupState.isGrouping, groupState.selectedComponents, dragState.justFinishedDrag],
  );

  // 컴포넌트 드래그 시작
  const startComponentDrag = useCallback(
    (component: ComponentData, event: React.MouseEvent) => {
      event.preventDefault();
      const rect = canvasRef.current?.getBoundingClientRect();
      if (!rect) return;

      // 새로운 드래그 시작 시 justFinishedDrag 플래그 해제
      if (dragState.justFinishedDrag) {
        setDragState((prev) => ({
          ...prev,
          justFinishedDrag: false,
        }));
      }

      // 캔버스 내부의 상대 좌표 계산 (스크롤 없는 고정 캔버스)
      const relativeMouseX = event.clientX - rect.left;
      const relativeMouseY = event.clientY - rect.top;

      // 다중 선택된 컴포넌트들 확인
      const isDraggedComponentSelected = groupState.selectedComponents.includes(component.id);
      let componentsToMove = isDraggedComponentSelected
        ? layout.components.filter((comp) => groupState.selectedComponents.includes(comp.id))
        : [component];

      // 레이아웃 컴포넌트인 경우 존에 속한 컴포넌트들도 함께 이동
      if (component.type === "layout") {
        const zoneComponents = layout.components.filter((comp) => comp.parentId === component.id && comp.zoneId);

        console.log("🏗️ 레이아웃 드래그 - 존 컴포넌트들 포함:", {
          layoutId: component.id,
          zoneComponentsCount: zoneComponents.length,
          zoneComponents: zoneComponents.map((c) => ({ id: c.id, zoneId: c.zoneId })),
        });

        // 중복 제거하여 추가
        const allComponentIds = new Set(componentsToMove.map((c) => c.id));
        const additionalComponents = zoneComponents.filter((c) => !allComponentIds.has(c.id));
        componentsToMove = [...componentsToMove, ...additionalComponents];
      }

      console.log("드래그 시작:", component.id, "이동할 컴포넌트 수:", componentsToMove.length);
      console.log("마우스 위치:", {
        clientX: event.clientX,
        clientY: event.clientY,
        rectLeft: rect.left,
        rectTop: rect.top,
        relativeX: relativeMouseX,
        relativeY: relativeMouseY,
        componentX: component.position.x,
        componentY: component.position.y,
        grabOffsetX: relativeMouseX - component.position.x,
        grabOffsetY: relativeMouseY - component.position.y,
      });

      console.log("🚀 드래그 시작:", {
        componentId: component.id,
        componentType: component.type,
        initialPosition: { x: component.position.x, y: component.position.y },
      });

      setDragState({
        isDragging: true,
        draggedComponent: component, // 주 드래그 컴포넌트 (마우스 위치 기준)
        draggedComponents: componentsToMove, // 함께 이동할 모든 컴포넌트들
        originalPosition: {
          x: component.position.x,
          y: component.position.y,
          z: (component.position as Position).z || 1,
        },
        currentPosition: {
          x: component.position.x,
          y: component.position.y,
          z: (component.position as Position).z || 1,
        },
        grabOffset: {
          x: relativeMouseX - component.position.x,
          y: relativeMouseY - component.position.y,
        },
        justFinishedDrag: false,
      });
    },
    [groupState.selectedComponents, layout.components, dragState.justFinishedDrag],
  );

  // 드래그 중 위치 업데이트 (성능 최적화 + 실시간 업데이트)
  const updateDragPosition = useCallback(
    (event: MouseEvent) => {
      if (!dragState.isDragging || !dragState.draggedComponent || !canvasRef.current) return;

      const rect = canvasRef.current.getBoundingClientRect();

      // 캔버스 내부의 상대 좌표 계산 (스크롤 없는 고정 캔버스)
      const relativeMouseX = event.clientX - rect.left;
      const relativeMouseY = event.clientY - rect.top;

      const newPosition = {
        x: relativeMouseX - dragState.grabOffset.x,
        y: relativeMouseY - dragState.grabOffset.y,
        z: (dragState.draggedComponent.position as Position).z || 1,
      };

      // 드래그 상태 업데이트
      console.log("🔥 ScreenDesigner updateDragPosition:", {
        draggedComponentId: dragState.draggedComponent.id,
        oldPosition: dragState.currentPosition,
        newPosition: newPosition,
      });

      setDragState((prev) => {
        const newState = {
          ...prev,
          currentPosition: { ...newPosition }, // 새로운 객체 생성
        };
        console.log("🔄 ScreenDesigner dragState 업데이트:", {
          prevPosition: prev.currentPosition,
          newPosition: newState.currentPosition,
          stateChanged:
            prev.currentPosition.x !== newState.currentPosition.x ||
            prev.currentPosition.y !== newState.currentPosition.y,
        });
        return newState;
      });

      // 성능 최적화: 드래그 중에는 상태 업데이트만 하고,
      // 실제 레이아웃 업데이트는 endDrag에서 처리
      // 속성 패널에서는 dragState.currentPosition을 참조하여 실시간 표시
    },
    [dragState.isDragging, dragState.draggedComponent, dragState.grabOffset],
  );

  // 드래그 종료
  const endDrag = useCallback(() => {
    if (dragState.isDragging && dragState.draggedComponent) {
      // 주 드래그 컴포넌트의 최종 위치 계산
      const draggedComponent = layout.components.find((c) => c.id === dragState.draggedComponent);
      let finalPosition = dragState.currentPosition;

      // 현재 해상도에 맞는 격자 정보 계산
      const currentGridInfo = layout.gridSettings
        ? calculateGridInfo(screenResolution.width, screenResolution.height, {
            columns: layout.gridSettings.columns,
            gap: layout.gridSettings.gap,
            padding: layout.gridSettings.padding,
            snapToGrid: layout.gridSettings.snapToGrid || false,
          })
        : null;

      // 일반 컴포넌트만 격자 스냅 적용 (그룹 제외)
      if (draggedComponent?.type !== "group" && layout.gridSettings?.snapToGrid && currentGridInfo) {
        finalPosition = snapToGrid(
          {
            x: dragState.currentPosition.x,
            y: dragState.currentPosition.y,
            z: dragState.currentPosition.z ?? 1,
          },
          currentGridInfo,
          {
            columns: layout.gridSettings.columns,
            gap: layout.gridSettings.gap,
            padding: layout.gridSettings.padding,
            snapToGrid: layout.gridSettings.snapToGrid || false,
          },
        );

        console.log("🎯 격자 스냅 적용됨:", {
          resolution: `${screenResolution.width}x${screenResolution.height}`,
          originalPosition: dragState.currentPosition,
          snappedPosition: finalPosition,
          columnWidth: currentGridInfo.columnWidth,
        });
      }

      // 스냅으로 인한 추가 이동 거리 계산
      const snapDeltaX = finalPosition.x - dragState.currentPosition.x;
      const snapDeltaY = finalPosition.y - dragState.currentPosition.y;

      // 원래 이동 거리 + 스냅 조정 거리
      const totalDeltaX = dragState.currentPosition.x - dragState.originalPosition.x + snapDeltaX;
      const totalDeltaY = dragState.currentPosition.y - dragState.originalPosition.y + snapDeltaY;

      // 다중 컴포넌트들의 최종 위치 업데이트
      const updatedComponents = layout.components.map((comp) => {
        const isDraggedComponent = dragState.draggedComponents.some((dragComp) => dragComp.id === comp.id);
        if (isDraggedComponent) {
          const originalComponent = dragState.draggedComponents.find((dragComp) => dragComp.id === comp.id)!;
          let newPosition = {
            x: originalComponent.position.x + totalDeltaX,
            y: originalComponent.position.y + totalDeltaY,
            z: originalComponent.position.z || 1,
          };

          // 그룹 내부 컴포넌트인 경우 패딩을 고려한 격자 스냅 적용
          if (comp.parentId && layout.gridSettings?.snapToGrid && gridInfo) {
            const { columnWidth } = gridInfo;
            const { gap } = layout.gridSettings;

            // 그룹 내부 패딩 고려한 격자 정렬
            const padding = 16;
            const effectiveX = newPosition.x - padding;
            const columnIndex = Math.round(effectiveX / (columnWidth + (gap || 16)));
            const snappedX = padding + columnIndex * (columnWidth + (gap || 16));

            // Y 좌표는 20px 단위로 스냅
            const effectiveY = newPosition.y - padding;
            const rowIndex = Math.round(effectiveY / 20);
            const snappedY = padding + rowIndex * 20;

            // 크기도 외부 격자와 동일하게 스냅
            const fullColumnWidth = columnWidth + (gap || 16); // 외부 격자와 동일한 크기
            const widthInColumns = Math.max(1, Math.round(comp.size.width / fullColumnWidth));
            const snappedWidth = widthInColumns * fullColumnWidth - (gap || 16); // gap 제거하여 실제 컴포넌트 크기
            const snappedHeight = Math.max(40, Math.round(comp.size.height / 20) * 20);

            newPosition = {
              x: Math.max(padding, snappedX), // 패딩만큼 최소 여백 확보
              y: Math.max(padding, snappedY),
              z: newPosition.z,
            };

            // 크기도 업데이트
            const newSize = {
              width: snappedWidth,
              height: snappedHeight,
            };

            console.log("🎯 드래그 종료 시 그룹 내부 컴포넌트 격자 스냅 (패딩 고려):", {
              componentId: comp.id,
              parentId: comp.parentId,
              beforeSnap: {
                x: originalComponent.position.x + totalDeltaX,
                y: originalComponent.position.y + totalDeltaY,
              },
              calculation: {
                effectiveX,
                effectiveY,
                columnIndex,
                rowIndex,
                columnWidth,
                fullColumnWidth,
                widthInColumns,
                gap: gap || 16,
                padding,
              },
              afterSnap: newPosition,
              afterSizeSnap: newSize,
            });

            return {
              ...comp,
              position: newPosition as Position,
              size: newSize,
            };
          }

          return {
            ...comp,
            position: newPosition as Position,
          };
        }
        return comp;
      });

      const newLayout = { ...layout, components: updatedComponents };
      setLayout(newLayout);

      // 선택된 컴포넌트도 업데이트 (PropertiesPanel 동기화용)
      if (selectedComponent && dragState.draggedComponents.some((c) => c.id === selectedComponent.id)) {
        const updatedSelectedComponent = updatedComponents.find((c) => c.id === selectedComponent.id);
        if (updatedSelectedComponent) {
          console.log("🔄 ScreenDesigner: 선택된 컴포넌트 위치 업데이트", {
            componentId: selectedComponent.id,
            oldPosition: selectedComponent.position,
            newPosition: updatedSelectedComponent.position,
          });
          setSelectedComponent(updatedSelectedComponent);
        }
      }

      // 히스토리에 저장
      saveToHistory(newLayout);
    }

    setDragState({
      isDragging: false,
      draggedComponent: null,
      draggedComponents: [],
      originalPosition: { x: 0, y: 0, z: 1 },
      currentPosition: { x: 0, y: 0, z: 1 },
      grabOffset: { x: 0, y: 0 },
      justFinishedDrag: true,
    });

    // 짧은 시간 후 justFinishedDrag 플래그 해제
    setTimeout(() => {
      setDragState((prev) => ({
        ...prev,
        justFinishedDrag: false,
      }));
    }, 100);
  }, [dragState, layout, gridInfo, saveToHistory]);

  // 드래그 선택 시작
  const startSelectionDrag = useCallback(
    (event: React.MouseEvent) => {
      if (dragState.isDragging) return; // 컴포넌트 드래그 중이면 무시

      const rect = canvasRef.current?.getBoundingClientRect();
      if (!rect) return;

      const startPoint = {
        x: event.clientX - rect.left,
        y: event.clientY - rect.top,
        z: 1,
      };

      setSelectionDrag({
        isSelecting: true,
        startPoint,
        currentPoint: startPoint,
        wasSelecting: false,
      });
    },
    [dragState.isDragging],
  );

  // 드래그 선택 업데이트
  const updateSelectionDrag = useCallback(
    (event: MouseEvent) => {
      if (!selectionDrag.isSelecting || !canvasRef.current) return;

      const rect = canvasRef.current.getBoundingClientRect();
      const currentPoint = {
        x: event.clientX - rect.left,
        y: event.clientY - rect.top,
        z: 1,
      };

      setSelectionDrag((prev) => ({
        ...prev,
        currentPoint,
      }));

      // 선택 영역 내의 컴포넌트들 찾기
      const selectionRect = {
        left: Math.min(selectionDrag.startPoint.x, currentPoint.x),
        top: Math.min(selectionDrag.startPoint.y, currentPoint.y),
        right: Math.max(selectionDrag.startPoint.x, currentPoint.x),
        bottom: Math.max(selectionDrag.startPoint.y, currentPoint.y),
      };

      const selectedIds = layout.components
        .filter((comp) => {
          const compRect = {
            left: comp.position.x,
            top: comp.position.y,
            right: comp.position.x + comp.size.width,
            bottom: comp.position.y + comp.size.height,
          };

          return (
            compRect.left < selectionRect.right &&
            compRect.right > selectionRect.left &&
            compRect.top < selectionRect.bottom &&
            compRect.bottom > selectionRect.top
          );
        })
        .map((comp) => comp.id);

      setGroupState((prev) => ({
        ...prev,
        selectedComponents: selectedIds,
      }));
    },
    [selectionDrag.isSelecting, selectionDrag.startPoint, layout.components],
  );

  // 드래그 선택 종료
  const endSelectionDrag = useCallback(() => {
    // 최소 드래그 거리 확인 (5픽셀)
    const minDragDistance = 5;
    const dragDistance = Math.sqrt(
      Math.pow(selectionDrag.currentPoint.x - selectionDrag.startPoint.x, 2) +
        Math.pow(selectionDrag.currentPoint.y - selectionDrag.startPoint.y, 2),
    );

    const wasActualDrag = dragDistance > minDragDistance;

    setSelectionDrag({
      isSelecting: false,
      startPoint: { x: 0, y: 0, z: 1 },
      currentPoint: { x: 0, y: 0, z: 1 },
      wasSelecting: wasActualDrag, // 실제 드래그였을 때만 클릭 이벤트 무시
    });

    // 짧은 시간 후 wasSelecting을 false로 리셋
    setTimeout(() => {
      setSelectionDrag((prev) => ({
        ...prev,
        wasSelecting: false,
      }));
    }, 100);
  }, [selectionDrag.currentPoint, selectionDrag.startPoint]);

  // 컴포넌트 삭제 (단일/다중 선택 지원)
  const deleteComponent = useCallback(() => {
    // 다중 선택된 컴포넌트가 있는 경우
    if (groupState.selectedComponents.length > 0) {
      console.log("🗑️ 다중 컴포넌트 삭제:", groupState.selectedComponents.length, "개");

      let newComponents = [...layout.components];

      // 각 선택된 컴포넌트를 삭제 처리
      groupState.selectedComponents.forEach((componentId) => {
        const component = layout.components.find((comp) => comp.id === componentId);
        if (!component) return;

        if (component.type === "group") {
          // 그룹 삭제 시: 자식 컴포넌트들의 절대 위치 복원
          const childComponents = newComponents.filter((comp) => comp.parentId === component.id);
          const restoredChildren = restoreAbsolutePositions(childComponents, component.position);

          newComponents = newComponents
            .map((comp) => {
              if (comp.parentId === component.id) {
                // 복원된 절대 위치로 업데이트
                const restoredChild = restoredChildren.find((restored) => restored.id === comp.id);
                return restoredChild || { ...comp, parentId: undefined };
              }
              return comp;
            })
            .filter((comp) => comp.id !== component.id); // 그룹 컴포넌트 제거
        } else {
          // 일반 컴포넌트 삭제
          newComponents = newComponents.filter((comp) => comp.id !== component.id);
        }
      });

      const newLayout = { ...layout, components: newComponents };
      setLayout(newLayout);
      saveToHistory(newLayout);

      // 선택 상태 초기화
      setSelectedComponent(null);
      setGroupState((prev) => ({ ...prev, selectedComponents: [] }));

      toast.success(`${groupState.selectedComponents.length}개 컴포넌트가 삭제되었습니다.`);
      return;
    }

    // 단일 선택된 컴포넌트 삭제
    if (!selectedComponent) return;

    console.log("🗑️ 단일 컴포넌트 삭제:", selectedComponent.id);

    let newComponents;

    if (selectedComponent.type === "group") {
      // 그룹 삭제 시: 자식 컴포넌트들의 절대 위치 복원 후 그룹 삭제
      const childComponents = layout.components.filter((comp) => comp.parentId === selectedComponent.id);
      const restoredChildren = restoreAbsolutePositions(childComponents, selectedComponent.position);

      newComponents = layout.components
        .map((comp) => {
          if (comp.parentId === selectedComponent.id) {
            // 복원된 절대 위치로 업데이트
            const restoredChild = restoredChildren.find((restored) => restored.id === comp.id);
            return restoredChild || { ...comp, parentId: undefined };
          }
          return comp;
        })
        .filter((comp) => comp.id !== selectedComponent.id); // 그룹 컴포넌트 제거
    } else {
      // 일반 컴포넌트 삭제
      newComponents = layout.components.filter((comp) => comp.id !== selectedComponent.id);
    }

    const newLayout = { ...layout, components: newComponents };

    setLayout(newLayout);
    saveToHistory(newLayout);
    setSelectedComponent(null);
    toast.success("컴포넌트가 삭제되었습니다.");
  }, [selectedComponent, groupState.selectedComponents, layout, saveToHistory]);

  // 컴포넌트 복사
  const copyComponent = useCallback(() => {
    if (groupState.selectedComponents.length > 0) {
      // 다중 선택된 컴포넌트들 복사
      const componentsToCopy = layout.components.filter((comp) => groupState.selectedComponents.includes(comp.id));
      setClipboard(componentsToCopy);
      console.log("다중 컴포넌트 복사:", componentsToCopy.length, "개");
      toast.success(`${componentsToCopy.length}개 컴포넌트가 복사되었습니다.`);
    } else if (selectedComponent) {
      // 단일 컴포넌트 복사
      setClipboard([selectedComponent]);
      console.log("단일 컴포넌트 복사:", selectedComponent.id);
      toast.success("컴포넌트가 복사되었습니다.");
    }
  }, [selectedComponent, groupState.selectedComponents, layout.components]);

  // 컴포넌트 붙여넣기
  const pasteComponent = useCallback(() => {
    if (clipboard.length === 0) {
      toast.warning("복사된 컴포넌트가 없습니다.");
      return;
    }

    const newComponents: ComponentData[] = [];
    const offset = 20; // 붙여넣기 시 위치 오프셋

    clipboard.forEach((clipComponent, index) => {
      const newComponent: ComponentData = {
        ...clipComponent,
        id: generateComponentId(),
        position: {
          x: clipComponent.position.x + offset + index * 10,
          y: clipComponent.position.y + offset + index * 10,
          z: clipComponent.position.z || 1,
        } as Position,
        parentId: undefined, // 붙여넣기 시 부모 관계 해제
      };
      newComponents.push(newComponent);
    });

    const newLayout = {
      ...layout,
      components: [...layout.components, ...newComponents],
    };

    setLayout(newLayout);
    saveToHistory(newLayout);

    // 붙여넣은 컴포넌트들을 선택 상태로 만들기
    setGroupState((prev) => ({
      ...prev,
      selectedComponents: newComponents.map((comp) => comp.id),
    }));

    console.log("컴포넌트 붙여넣기 완료:", newComponents.length, "개");
    toast.success(`${newComponents.length}개 컴포넌트가 붙여넣어졌습니다.`);
  }, [clipboard, layout, saveToHistory]);

  // 그룹 생성 (임시 비활성화)
  const handleGroupCreate = useCallback(
    (componentIds: string[], title: string, style?: any) => {
      console.log("그룹 생성 기능이 임시 비활성화되었습니다.");
      toast.info("그룹 기능이 임시 비활성화되었습니다.");
      return;

      // 격자 정보 계산
      const currentGridInfo =
        gridInfo ||
        calculateGridInfo(
          1200,
          800,
          layout.gridSettings || {
            columns: 12,
            gap: 16,
            padding: 16,
            snapToGrid: true,
            showGrid: true,
            gridColor: "#d1d5db",
            gridOpacity: 0.5,
          },
        );

      console.log("🔧 그룹 생성 시작:", {
        selectedCount: selectedComponents.length,
        snapToGrid: layout.gridSettings?.snapToGrid,
        gridInfo: currentGridInfo,
      });

      // 컴포넌트 크기 조정 기반 그룹 크기 계산
      const calculateOptimalGroupSize = () => {
        if (!currentGridInfo || !layout.gridSettings?.snapToGrid) {
          // 격자 스냅이 비활성화된 경우 기본 패딩 사용
          const boundingBox = calculateBoundingBox(selectedComponents);
          const padding = 40;
          return {
            boundingBox,
            groupPosition: { x: boundingBox.minX - padding, y: boundingBox.minY - padding, z: 1 },
            groupSize: { width: boundingBox.width + padding * 2, height: boundingBox.height + padding * 2 },
            gridColumns: 1,
            scaledComponents: selectedComponents, // 크기 조정 없음
            padding: padding,
          };
        }

        const { columnWidth } = currentGridInfo;
        const gap = layout.gridSettings?.gap || 16;
        const contentBoundingBox = calculateBoundingBox(selectedComponents);

        // 1. 간단한 접근: 컴포넌트들의 시작점에서 가장 가까운 격자 시작점 찾기
        const startColumn = Math.floor(contentBoundingBox.minX / (columnWidth + gap));

        // 2. 컴포넌트들의 끝점까지 포함할 수 있는 컬럼 수 계산
        const groupStartX = startColumn * (columnWidth + gap);
        const availableWidthFromStart = contentBoundingBox.maxX - groupStartX;
        const currentWidthInColumns = Math.ceil(availableWidthFromStart / (columnWidth + gap));

        // 2. 그룹은 격자에 정확히 맞게 위치와 크기 설정
        const padding = 20;
        const groupX = startColumn * (columnWidth + gap); // 격자 시작점에 정확히 맞춤
        const groupY = contentBoundingBox.minY - padding;
        const groupWidth = currentWidthInColumns * columnWidth + (currentWidthInColumns - 1) * gap; // 컬럼 크기 + gap
        const groupHeight = contentBoundingBox.height + padding * 2;

        // 4. 내부 컴포넌트들을 그룹 크기에 맞게 스케일링
        const availableWidth = groupWidth - padding * 2; // 패딩 제외한 실제 사용 가능 너비
        const scaleFactorX = availableWidth / contentBoundingBox.width;

        const scaledComponents = selectedComponents.map((comp) => {
          // 컴포넌트의 원래 위치에서 컨텐츠 영역 시작점까지의 상대 위치 계산
          const relativeX = comp.position.x - contentBoundingBox.minX;
          const relativeY = comp.position.y - contentBoundingBox.minY;

          return {
            ...comp,
            position: {
              x: padding + relativeX * scaleFactorX, // 패딩 + 스케일된 상대 위치
              y: padding + relativeY, // Y는 스케일링 없이 패딩만 적용
              z: comp.position.z || 1,
            },
            size: {
              width: comp.size.width * scaleFactorX, // X 방향 스케일링
              height: comp.size.height, // Y는 원본 크기 유지
            },
          };
        });

        console.log("🎯 컴포넌트 크기 조정 기반 그룹 생성:", {
          originalBoundingBox: contentBoundingBox,
          gridCalculation: {
            columnWidthPlusGap: columnWidth + gap,
            startColumn: `Math.floor(${contentBoundingBox.minX} / ${columnWidth + gap}) = ${startColumn}`,
            groupStartX: `${startColumn} * ${columnWidth + gap} = ${groupStartX}`,
            availableWidthFromStart: `${contentBoundingBox.maxX} - ${groupStartX} = ${availableWidthFromStart}`,
            currentWidthInColumns: `Math.ceil(${availableWidthFromStart} / ${columnWidth + gap}) = ${currentWidthInColumns}`,
            finalGroupX: `${startColumn} * ${columnWidth + gap} = ${groupX}`,
            actualGroupWidth: `${currentWidthInColumns}컬럼 * ${columnWidth}px + ${currentWidthInColumns - 1}gap * ${gap}px = ${groupWidth}px`,
          },
          groupPosition: { x: groupX, y: groupY },
          groupSize: { width: groupWidth, height: groupHeight },
          scaleFactorX,
          availableWidth,
          padding,
          scaledComponentsCount: scaledComponents.length,
          scaledComponentsDetails: scaledComponents.map((comp) => {
            const original = selectedComponents.find((c) => c.id === comp.id);
            return {
              id: comp.id,
              originalPos: original?.position,
              scaledPos: comp.position,
              originalSize: original?.size,
              scaledSize: comp.size,
              deltaX: comp.position.x - (original?.position.x || 0),
              deltaY: comp.position.y - (original?.position.y || 0),
            };
          }),
        });

        return {
          boundingBox: contentBoundingBox,
          groupPosition: { x: groupX, y: groupY, z: 1 },
          groupSize: { width: groupWidth, height: groupHeight },
          gridColumns: currentWidthInColumns,
          scaledComponents: scaledComponents, // 스케일된 컴포넌트들
          padding: padding,
        };
      };

      const {
        boundingBox,
        groupPosition,
        groupSize: optimizedGroupSize,
        gridColumns,
        scaledComponents,
        padding,
      } = calculateOptimalGroupSize();

      // 스케일된 컴포넌트들로 상대 위치 계산 (이미 최적화되어 추가 격자 정렬 불필요)
      const relativeChildren = calculateRelativePositions(
        scaledComponents,
        groupPosition,
        "temp", // 임시 그룹 ID
      );

      console.log("📏 최적화된 그룹 생성 (컴포넌트 스케일링):", {
        gridColumns,
        groupSize: optimizedGroupSize,
        groupPosition,
        scaledComponentsCount: scaledComponents.length,
        padding,
        strategy: "내부 컴포넌트 크기 조정으로 격자 정확 맞춤",
      });

      // 그룹 컴포넌트 생성 (gridColumns 속성 포함)
      const groupComponent = createGroupComponent(componentIds, title, groupPosition, optimizedGroupSize, style);

      // 그룹에 계산된 gridColumns 속성 추가
      groupComponent.gridColumns = gridColumns;

      // 실제 그룹 ID로 자식들 업데이트
      const finalChildren = relativeChildren.map((child) => ({
        ...child,
        parentId: groupComponent.id,
      }));

      const newLayout = {
        ...layout,
        components: [
          ...layout.components.filter((comp) => !componentIds.includes(comp.id)),
          groupComponent,
          ...finalChildren,
        ],
      };

      setLayout(newLayout);
      saveToHistory(newLayout);
      setGroupState((prev) => ({
        ...prev,
        selectedComponents: [groupComponent.id],
        isGrouping: false,
      }));
      setSelectedComponent(groupComponent);

      console.log("🎯 최적화된 그룹 생성 완료:", {
        groupId: groupComponent.id,
        childrenCount: finalChildren.length,
        position: groupPosition,
        size: optimizedGroupSize,
        gridColumns: groupComponent.gridColumns,
        componentsScaled: !!scaledComponents.length,
        gridAligned: layout.gridSettings?.snapToGrid,
      });

      toast.success(`그룹이 생성되었습니다 (${finalChildren.length}개 컴포넌트)`);
    },
    [layout, saveToHistory, gridInfo],
  );

  // 그룹 생성 함수 (다이얼로그 표시)
  const createGroup = useCallback(() => {
    if (groupState.selectedComponents.length < 2) {
      toast.warning("그룹을 만들려면 2개 이상의 컴포넌트를 선택해야 합니다.");
      return;
    }

    console.log("🔄 그룹 생성 다이얼로그 표시");
    setShowGroupCreateDialog(true);
  }, [groupState.selectedComponents]);

  // 그룹 해제 함수 (임시 비활성화)
  const ungroupComponents = useCallback(() => {
    console.log("그룹 해제 기능이 임시 비활성화되었습니다.");
    toast.info("그룹 해제 기능이 임시 비활성화되었습니다.");
    return;

    const groupId = selectedComponent.id;

    // 자식 컴포넌트들의 절대 위치 복원
    const childComponents = layout.components.filter((comp) => comp.parentId === groupId);
    const restoredChildren = restoreAbsolutePositions(childComponents, selectedComponent.position);

    // 자식 컴포넌트들의 위치 복원 및 parentId 제거
    const updatedComponents = layout.components
      .map((comp) => {
        if (comp.parentId === groupId) {
          const restoredChild = restoredChildren.find((restored) => restored.id === comp.id);
          return restoredChild || { ...comp, parentId: undefined };
        }
        return comp;
      })
      .filter((comp) => comp.id !== groupId); // 그룹 컴포넌트 제거

    const newLayout = { ...layout, components: updatedComponents };
    setLayout(newLayout);
    saveToHistory(newLayout);

    // 선택 상태 초기화
    setSelectedComponent(null);
    setGroupState((prev) => ({ ...prev, selectedComponents: [] }));
  }, [selectedComponent, layout, saveToHistory]);

  // 마우스 이벤트 처리 (드래그 및 선택) - 성능 최적화
  useEffect(() => {
    let animationFrameId: number;

    const handleMouseMove = (e: MouseEvent) => {
      if (dragState.isDragging) {
        // requestAnimationFrame으로 부드러운 애니메이션
        if (animationFrameId) {
          cancelAnimationFrame(animationFrameId);
        }
        animationFrameId = requestAnimationFrame(() => {
          updateDragPosition(e);
        });
      } else if (selectionDrag.isSelecting) {
        updateSelectionDrag(e);
      }
    };

    const handleMouseUp = () => {
      if (dragState.isDragging) {
        if (animationFrameId) {
          cancelAnimationFrame(animationFrameId);
        }
        endDrag();
      } else if (selectionDrag.isSelecting) {
        endSelectionDrag();
      }
    };

    if (dragState.isDragging || selectionDrag.isSelecting) {
      document.addEventListener("mousemove", handleMouseMove, { passive: true });
      document.addEventListener("mouseup", handleMouseUp);

      return () => {
        if (animationFrameId) {
          cancelAnimationFrame(animationFrameId);
        }
        document.removeEventListener("mousemove", handleMouseMove);
        document.removeEventListener("mouseup", handleMouseUp);
      };
    }
  }, [
    dragState.isDragging,
    selectionDrag.isSelecting,
    updateDragPosition,
    endDrag,
    updateSelectionDrag,
    endSelectionDrag,
  ]);

  // 캔버스 크기 초기화 및 리사이즈 이벤트 처리
  useEffect(() => {
    const updateCanvasSize = () => {
      if (canvasRef.current) {
        const rect = canvasRef.current.getBoundingClientRect();
        setCanvasSize({ width: rect.width, height: rect.height });
      }
    };

    // 초기 크기 설정
    updateCanvasSize();

    // 리사이즈 이벤트 리스너
    window.addEventListener("resize", updateCanvasSize);

    return () => window.removeEventListener("resize", updateCanvasSize);
  }, []);

  // 컴포넌트 마운트 후 캔버스 크기 업데이트
  useEffect(() => {
    const timer = setTimeout(() => {
      if (canvasRef.current) {
        const rect = canvasRef.current.getBoundingClientRect();
        setCanvasSize({ width: rect.width, height: rect.height });
      }
    }, 100);

    return () => clearTimeout(timer);
  }, [selectedScreen]);

  // 키보드 이벤트 처리 (브라우저 기본 기능 완전 차단)
  useEffect(() => {
    const handleKeyDown = async (e: KeyboardEvent) => {
      console.log("🎯 키 입력 감지:", { key: e.key, ctrlKey: e.ctrlKey, shiftKey: e.shiftKey, metaKey: e.metaKey });

      // 🚫 브라우저 기본 단축키 완전 차단 목록
      const browserShortcuts = [
        // 검색 관련
        { ctrl: true, key: "f" }, // 페이지 내 검색
        { ctrl: true, key: "g" }, // 다음 검색 결과
        { ctrl: true, shift: true, key: "g" }, // 이전 검색 결과
        { ctrl: true, key: "h" }, // 검색 기록

        // 탭/창 관리
        { ctrl: true, key: "t" }, // 새 탭
        { ctrl: true, key: "w" }, // 탭 닫기
        { ctrl: true, shift: true, key: "t" }, // 닫힌 탭 복원
        { ctrl: true, key: "n" }, // 새 창
        { ctrl: true, shift: true, key: "n" }, // 시크릿 창

        // 페이지 관리
        { ctrl: true, key: "r" }, // 새로고침
        { ctrl: true, shift: true, key: "r" }, // 강제 새로고침
        { ctrl: true, key: "d" }, // 북마크 추가
        { ctrl: true, shift: true, key: "d" }, // 모든 탭 북마크

        // 편집 관련 (필요시에만 허용)
        { ctrl: true, key: "s" }, // 저장 (필요시 차단 해제)
        { ctrl: true, key: "p" }, // 인쇄
        { ctrl: true, key: "o" }, // 파일 열기
        { ctrl: true, key: "v" }, // 붙여넣기 (브라우저 기본 동작 차단)

        // 개발자 도구
        { key: "F12" }, // 개발자 도구
        { ctrl: true, shift: true, key: "i" }, // 개발자 도구
        { ctrl: true, shift: true, key: "c" }, // 요소 검사
        { ctrl: true, shift: true, key: "j" }, // 콘솔
        { ctrl: true, key: "u" }, // 소스 보기

        // 기타
        { ctrl: true, key: "j" }, // 다운로드
        { ctrl: true, shift: true, key: "delete" }, // 브라우징 데이터 삭제
        { ctrl: true, key: "+" }, // 확대
        { ctrl: true, key: "-" }, // 축소
        { ctrl: true, key: "0" }, // 확대/축소 초기화
      ];

      // 브라우저 기본 단축키 체크 및 차단
      const isBrowserShortcut = browserShortcuts.some((shortcut) => {
        const ctrlMatch = shortcut.ctrl ? e.ctrlKey || e.metaKey : true;
        const shiftMatch = shortcut.shift ? e.shiftKey : !e.shiftKey;
        const keyMatch = e.key?.toLowerCase() === shortcut.key?.toLowerCase();
        return ctrlMatch && shiftMatch && keyMatch;
      });

      if (isBrowserShortcut) {
        console.log("🚫 브라우저 기본 단축키 차단:", e.key);
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
      }

      // ✅ 애플리케이션 전용 단축키 처리

      // 1. 그룹 관련 단축키
      if ((e.ctrlKey || e.metaKey) && e.key?.toLowerCase() === "g" && !e.shiftKey) {
        console.log("🔄 그룹 생성 단축키");
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();

        if (groupState.selectedComponents.length >= 2) {
          console.log("✅ 그룹 생성 실행");
          createGroup();
        } else {
          console.log("⚠️ 선택된 컴포넌트가 부족함 (2개 이상 필요)");
        }
        return false;
      }

      if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key?.toLowerCase() === "g") {
        console.log("🔄 그룹 해제 단축키");
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();

        if (selectedComponent && selectedComponent.type === "group") {
          console.log("✅ 그룹 해제 실행");
          ungroupComponents();
        } else {
          console.log("⚠️ 선택된 그룹이 없음");
        }
        return false;
      }

      // 2. 전체 선택 (애플리케이션 내에서만)
      if ((e.ctrlKey || e.metaKey) && e.key?.toLowerCase() === "a") {
        console.log("🔄 전체 선택 (애플리케이션 내)");
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
        const allComponentIds = layout.components.map((comp) => comp.id);
        setGroupState((prev) => ({ ...prev, selectedComponents: allComponentIds }));
        return false;
      }

      // 3. 실행취소/다시실행
      if ((e.ctrlKey || e.metaKey) && e.key?.toLowerCase() === "z" && !e.shiftKey) {
        console.log("🔄 실행취소");
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
        undo();
        return false;
      }

      if (
        ((e.ctrlKey || e.metaKey) && e.key?.toLowerCase() === "y") ||
        ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key?.toLowerCase() === "z")
      ) {
        console.log("🔄 다시실행");
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
        redo();
        return false;
      }

      // 4. 복사 (컴포넌트 복사)
      if ((e.ctrlKey || e.metaKey) && e.key?.toLowerCase() === "c") {
        console.log("🔄 컴포넌트 복사");
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
        copyComponent();
        return false;
      }

      // 5. 붙여넣기 (컴포넌트 붙여넣기)
      if ((e.ctrlKey || e.metaKey) && e.key?.toLowerCase() === "v") {
        console.log("🔄 컴포넌트 붙여넣기");
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
        pasteComponent();
        return false;
      }

      // 6. 삭제 (단일/다중 선택 지원)
      if (e.key === "Delete" && (selectedComponent || groupState.selectedComponents.length > 0)) {
        console.log("🗑️ 컴포넌트 삭제 (단축키)");
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
        deleteComponent();
        return false;
      }

      // 7. 선택 해제
      if (e.key === "Escape") {
        console.log("🔄 선택 해제");
        setSelectedComponent(null);
        setGroupState((prev) => ({ ...prev, selectedComponents: [], isGrouping: false }));
        return false;
      }

      // 8. 저장 (Ctrl+S는 레이아웃 저장용으로 사용)
      if ((e.ctrlKey || e.metaKey) && e.key?.toLowerCase() === "s") {
        console.log("💾 레이아웃 저장");
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();

        // 레이아웃 저장 실행
        if (layout.components.length > 0 && selectedScreen?.screenId) {
          setIsSaving(true);
          try {
            // 해상도 정보를 포함한 레이아웃 데이터 생성
            const layoutWithResolution = {
              ...layout,
              screenResolution: screenResolution,
            };
            console.log("⚡ 자동 저장할 레이아웃 데이터:", {
              componentsCount: layoutWithResolution.components.length,
              gridSettings: layoutWithResolution.gridSettings,
              screenResolution: layoutWithResolution.screenResolution,
            });
            await screenApi.saveLayout(selectedScreen.screenId, layoutWithResolution);
            toast.success("레이아웃이 저장되었습니다.");
          } catch (error) {
            console.error("레이아웃 저장 실패:", error);
            toast.error("레이아웃 저장에 실패했습니다.");
          } finally {
            setIsSaving(false);
          }
        } else {
          console.log("⚠️ 저장할 컴포넌트가 없습니다");
          toast.warning("저장할 컴포넌트가 없습니다.");
        }
        return false;
      }
    };

    // window 레벨에서 캡처 단계에서 가장 먼저 처리
    window.addEventListener("keydown", handleKeyDown, { capture: true, passive: false });
    return () => window.removeEventListener("keydown", handleKeyDown, { capture: true });
  }, [
    selectedComponent,
    deleteComponent,
    copyComponent,
    pasteComponent,
    undo,
    redo,
    createGroup,
    ungroupComponents,
    groupState.selectedComponents,
    layout,
    selectedScreen,
  ]);

  if (!selectedScreen) {
    return (
      <div className="flex h-full items-center justify-center">
        <div className="text-center">
          <Database className="mx-auto mb-4 h-12 w-12 text-gray-400" />
          <h3 className="text-lg font-medium text-gray-900">화면을 선택하세요</h3>
          <p className="text-gray-500">설계할 화면을 먼저 선택해주세요.</p>
        </div>
      </div>
    );
  }

  return (
    <div className="flex h-screen w-full flex-col bg-gray-100">
      {/* 상단 툴바 */}
      <DesignerToolbar
        screenName={selectedScreen?.screenName}
        tableName={selectedScreen?.tableName}
        onBack={onBackToList}
        onSave={handleSave}
        onUndo={undo}
        onRedo={redo}
        onPreview={() => {
          toast.info("미리보기 기능은 준비 중입니다.");
        }}
        onTogglePanel={togglePanel}
        panelStates={panelStates}
        canUndo={historyIndex > 0}
        canRedo={historyIndex < history.length - 1}
        isSaving={isSaving}
      />

      {/* 메인 캔버스 영역 (스크롤 가능한 컨테이너) */}
      <div className="relative flex-1 overflow-auto bg-gray-100 p-8">
        {/* 해상도 정보 표시 */}
        <div className="mb-4 flex items-center justify-center">
          <div className="rounded-lg border bg-white px-4 py-2 shadow-sm">
            <span className="text-sm font-medium text-gray-700">
              {screenResolution.name} ({screenResolution.width} × {screenResolution.height})
            </span>
          </div>
        </div>

        {/* 실제 작업 캔버스 (해상도 크기) */}
        <div
          className="mx-auto bg-white shadow-lg"
          style={{ width: screenResolution.width, height: screenResolution.height }}
        >
          <div
            ref={canvasRef}
            className="relative h-full w-full overflow-hidden bg-white"
            onClick={(e) => {
              if (e.target === e.currentTarget && !selectionDrag.wasSelecting) {
                setSelectedComponent(null);
                setGroupState((prev) => ({ ...prev, selectedComponents: [] }));
              }
            }}
            onMouseDown={(e) => {
              if (e.target === e.currentTarget) {
                startSelectionDrag(e);
              }
            }}
            onDragOver={(e) => {
              e.preventDefault();
              e.dataTransfer.dropEffect = "copy";
            }}
            onDrop={(e) => {
              e.preventDefault();
              console.log("🎯 캔버스 드롭 이벤트 발생");
              handleDrop(e);
            }}
          >
            {/* 격자 라인 */}
            {gridLines.map((line, index) => (
              <div
                key={index}
                className="pointer-events-none absolute"
                style={{
                  left: line.type === "vertical" ? `${line.position}px` : 0,
                  top: line.type === "horizontal" ? `${line.position}px` : 0,
                  width: line.type === "vertical" ? "1px" : "100%",
                  height: line.type === "horizontal" ? "1px" : "100%",
                  backgroundColor: layout.gridSettings?.gridColor || "#d1d5db",
                  opacity: layout.gridSettings?.gridOpacity || 0.5,
                }}
              />
            ))}

            {/* 컴포넌트들 */}
            {layout.components
              .filter((component) => !component.parentId) // 최상위 컴포넌트만 렌더링
              .map((component) => {
                const children =
                  component.type === "group"
                    ? layout.components.filter((child) => child.parentId === component.id)
                    : [];

                // 드래그 중 시각적 피드백 (다중 선택 지원)
                const isDraggingThis = dragState.isDragging && dragState.draggedComponent?.id === component.id;
                const isBeingDragged =
                  dragState.isDragging && dragState.draggedComponents.some((dragComp) => dragComp.id === component.id);

                let displayComponent = component;

                if (isBeingDragged) {
                  if (isDraggingThis) {
                    // 주 드래그 컴포넌트: 마우스 위치 기반으로 실시간 위치 업데이트
                    displayComponent = {
                      ...component,
                      position: dragState.currentPosition,
                      style: {
                        ...component.style,
                        opacity: 0.8,
                        transform: "scale(1.02)",
                        transition: "none",
                        zIndex: 9999,
                      },
                    };
                  } else {
                    // 다른 선택된 컴포넌트들: 상대적 위치로 실시간 업데이트
                    const originalComponent = dragState.draggedComponents.find(
                      (dragComp) => dragComp.id === component.id,
                    );
                    if (originalComponent) {
                      const deltaX = dragState.currentPosition.x - dragState.originalPosition.x;
                      const deltaY = dragState.currentPosition.y - dragState.originalPosition.y;

                      displayComponent = {
                        ...component,
                        position: {
                          x: originalComponent.position.x + deltaX,
                          y: originalComponent.position.y + deltaY,
                          z: originalComponent.position.z || 1,
                        } as Position,
                        style: {
                          ...component.style,
                          opacity: 0.8,
                          transition: "none",
                          zIndex: 8888, // 주 컴포넌트보다 약간 낮게
                        },
                      };
                    }
                  }
                }

                return (
                  <RealtimePreview
                    key={component.id}
                    component={displayComponent}
                    isSelected={
                      selectedComponent?.id === component.id || groupState.selectedComponents.includes(component.id)
                    }
                    isDesignMode={true} // 편집 모드로 설정
                    onClick={(e) => handleComponentClick(component, e)}
                    onDragStart={(e) => startComponentDrag(component, e)}
                    onDragEnd={endDrag}
                    selectedScreen={selectedScreen}
                    // onZoneComponentDrop 제거
                    onZoneClick={handleZoneClick}
                  >
                    {/* 컨테이너, 그룹, 영역의 자식 컴포넌트들 렌더링 (레이아웃은 독립적으로 렌더링) */}
                    {(component.type === "group" || component.type === "container" || component.type === "area") &&
                      layout.components
                        .filter((child) => child.parentId === component.id)
                        .map((child) => {
                          // 자식 컴포넌트에도 드래그 피드백 적용
                          const isChildDraggingThis =
                            dragState.isDragging && dragState.draggedComponent?.id === child.id;
                          const isChildBeingDragged =
                            dragState.isDragging &&
                            dragState.draggedComponents.some((dragComp) => dragComp.id === child.id);

                          let displayChild = child;

                          if (isChildBeingDragged) {
                            if (isChildDraggingThis) {
                              // 주 드래그 자식 컴포넌트
                              displayChild = {
                                ...child,
                                position: dragState.currentPosition,
                                style: {
                                  ...child.style,
                                  opacity: 0.8,
                                  transform: "scale(1.02)",
                                  transition: "none",
                                  zIndex: 9999,
                                },
                              };
                            } else {
                              // 다른 선택된 자식 컴포넌트들
                              const originalChildComponent = dragState.draggedComponents.find(
                                (dragComp) => dragComp.id === child.id,
                              );
                              if (originalChildComponent) {
                                const deltaX = dragState.currentPosition.x - dragState.originalPosition.x;
                                const deltaY = dragState.currentPosition.y - dragState.originalPosition.y;

                                displayChild = {
                                  ...child,
                                  position: {
                                    x: originalChildComponent.position.x + deltaX,
                                    y: originalChildComponent.position.y + deltaY,
                                    z: originalChildComponent.position.z || 1,
                                  } as Position,
                                  style: {
                                    ...child.style,
                                    opacity: 0.8,
                                    transition: "none",
                                    zIndex: 8888,
                                  },
                                };
                              }
                            }
                          }

                          // 자식 컴포넌트의 위치를 부모 기준 상대 좌표로 조정
                          const relativeChildComponent = {
                            ...displayChild,
                            position: {
                              x: displayChild.position.x - component.position.x,
                              y: displayChild.position.y - component.position.y,
                              z: displayChild.position.z || 1,
                            },
                          };

                          return (
                            <RealtimePreview
                              key={child.id}
                              component={relativeChildComponent}
                              isSelected={
                                selectedComponent?.id === child.id || groupState.selectedComponents.includes(child.id)
                              }
                              isDesignMode={true} // 편집 모드로 설정
                              onClick={(e) => handleComponentClick(child, e)}
                              onDragStart={(e) => startComponentDrag(child, e)}
                              onDragEnd={endDrag}
                              selectedScreen={selectedScreen}
                              // onZoneComponentDrop 제거
                              onZoneClick={handleZoneClick}
                            />
                          );
                        })}
                  </RealtimePreview>
                );
              })}

            {/* 드래그 선택 영역 */}
            {selectionDrag.isSelecting && (
              <div
                className="pointer-events-none absolute"
                style={{
                  left: `${Math.min(selectionDrag.startPoint.x, selectionDrag.currentPoint.x)}px`,
                  top: `${Math.min(selectionDrag.startPoint.y, selectionDrag.currentPoint.y)}px`,
                  width: `${Math.abs(selectionDrag.currentPoint.x - selectionDrag.startPoint.x)}px`,
                  height: `${Math.abs(selectionDrag.currentPoint.y - selectionDrag.startPoint.y)}px`,
                  border: "2px dashed #3b82f6",
                  backgroundColor: "rgba(59, 130, 246, 0.05)", // 매우 투명한 배경 (5%)
                  borderRadius: "4px",
                }}
              />
            )}

            {/* 빈 캔버스 안내 */}
            {layout.components.length === 0 && (
              <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
                <div className="text-center text-gray-400">
                  <Database className="mx-auto mb-4 h-16 w-16" />
                  <h3 className="mb-2 text-xl font-medium">캔버스가 비어있습니다</h3>
                  <p className="text-sm">좌측 패널에서 테이블/컬럼이나 템플릿을 드래그하여 화면을 설계하세요</p>
                  <p className="mt-2 text-xs">
                    단축키: T(테이블), M(템플릿), P(속성), S(스타일), R(격자), D(상세설정), E(해상도)
                  </p>
                  <p className="mt-1 text-xs">
                    편집: Ctrl+C(복사), Ctrl+V(붙여넣기), Ctrl+S(저장), Ctrl+Z(실행취소), Delete(삭제)
                  </p>
                  <p className="mt-1 text-xs text-amber-600">
                    ⚠️ 브라우저 기본 단축키가 차단되어 애플리케이션 기능만 작동합니다
                  </p>
                </div>
              </div>
            )}
          </div>
        </div>
      </div>

      {/* 플로팅 패널들 */}
      <FloatingPanel
        id="tables"
        title="테이블 목록"
        isOpen={panelStates.tables?.isOpen || false}
        onClose={() => closePanel("tables")}
        position="left"
        width={380}
        height={700}
        autoHeight={false}
      >
        <TablesPanel
          tables={filteredTables}
          searchTerm={searchTerm}
          onSearchChange={setSearchTerm}
          onDragStart={(e, table, column) => {
            console.log("🚀 드래그 시작:", { table: table.tableName, column: column?.columnName });
            const dragData = {
              type: column ? "column" : "table",
              table,
              column,
            };
            console.log("📦 드래그 데이터:", dragData);
            e.dataTransfer.setData("application/json", JSON.stringify(dragData));
          }}
          selectedTableName={selectedScreen.tableName}
        />
      </FloatingPanel>

      <FloatingPanel
        id="templates"
        title="템플릿"
        isOpen={panelStates.templates?.isOpen || false}
        onClose={() => closePanel("templates")}
        position="left"
        width={380}
        height={700}
        autoHeight={false}
      >
        <TemplatesPanel
          onDragStart={(e, template) => {
            // React 컴포넌트(icon)를 제외하고 JSON으로 직렬화 가능한 데이터만 전송
            const serializableTemplate = {
              id: template.id,
              name: template.name,
              description: template.description,
              category: template.category,
              defaultSize: template.defaultSize,
              components: template.components,
            };

            const dragData = {
              type: "template",
              template: serializableTemplate,
            };
            e.dataTransfer.setData("application/json", JSON.stringify(dragData));
          }}
        />
      </FloatingPanel>

      <FloatingPanel
        id="layouts"
        title="레이아웃"
        isOpen={panelStates.layouts?.isOpen || false}
        onClose={() => closePanel("layouts")}
        position="left"
        width={380}
        height={700}
        autoHeight={false}
      >
        <LayoutsPanel
          onDragStart={(e, layoutData) => {
            const dragData = {
              type: "layout",
              layout: layoutData,
            };
            e.dataTransfer.setData("application/json", JSON.stringify(dragData));
          }}
          gridSettings={layout.gridSettings || { columns: 12, gap: 16, padding: 16, snapToGrid: true }}
          screenResolution={screenResolution}
        />
      </FloatingPanel>

      <FloatingPanel
        id="components"
        title="컴포넌트"
        isOpen={panelStates.components?.isOpen || false}
        onClose={() => closePanel("components")}
        position="left"
        width={380}
        height={700}
        autoHeight={false}
      >
        <ComponentsPanel />
      </FloatingPanel>

      <FloatingPanel
        id="properties"
        title="속성 편집"
        isOpen={panelStates.properties?.isOpen || false}
        onClose={() => closePanel("properties")}
        position="right"
        width={360}
        height={400}
        autoHeight={true}
      >
        <PropertiesPanel
          key={`properties-${selectedComponent?.id}-${dragState.isDragging ? dragState.currentPosition.x + dragState.currentPosition.y : "static"}`}
          selectedComponent={selectedComponent || undefined}
          tables={tables}
          dragState={dragState}
          onUpdateProperty={(path: string, value: any) => {
            console.log("🔧 속성 업데이트 요청:", {
              componentId: selectedComponent?.id,
              componentType: selectedComponent?.type,
              path,
              value: typeof value === "object" ? JSON.stringify(value).substring(0, 100) + "..." : value,
            });
            if (selectedComponent) {
              updateComponentProperty(selectedComponent.id, path, value);
            }
          }}
          onDeleteComponent={deleteComponent}
          onCopyComponent={copyComponent}
        />
      </FloatingPanel>

      <FloatingPanel
        id="styles"
        title="스타일 편집"
        isOpen={panelStates.styles?.isOpen || false}
        onClose={() => closePanel("styles")}
        position="right"
        width={360}
        height={400}
        autoHeight={true}
      >
        {selectedComponent ? (
          <div className="p-4">
            <StyleEditor
              style={selectedComponent.style || {}}
              onStyleChange={(newStyle) => {
                console.log("🔧 StyleEditor 크기 변경:", {
                  componentId: selectedComponent.id,
                  newStyle,
                  currentSize: selectedComponent.size,
                  hasWidth: !!newStyle.width,
                  hasHeight: !!newStyle.height,
                });

                // 스타일 업데이트
                updateComponentProperty(selectedComponent.id, "style", newStyle);

                // 크기가 변경된 경우 component.size도 업데이트
                if (newStyle.width || newStyle.height) {
                  const width = newStyle.width
                    ? parseInt(newStyle.width.replace("px", ""))
                    : selectedComponent.size.width;
                  const height = newStyle.height
                    ? parseInt(newStyle.height.replace("px", ""))
                    : selectedComponent.size.height;

                  console.log("📏 크기 업데이트:", {
                    originalWidth: selectedComponent.size.width,
                    originalHeight: selectedComponent.size.height,
                    newWidth: width,
                    newHeight: height,
                    styleWidth: newStyle.width,
                    styleHeight: newStyle.height,
                  });

                  updateComponentProperty(selectedComponent.id, "size.width", width);
                  updateComponentProperty(selectedComponent.id, "size.height", height);
                }
              }}
            />
          </div>
        ) : (
          <div className="flex h-full items-center justify-center text-gray-500">
            컴포넌트를 선택하여 스타일을 편집하세요
          </div>
        )}
      </FloatingPanel>

      <FloatingPanel
        id="grid"
        title="격자 설정"
        isOpen={panelStates.grid?.isOpen || false}
        onClose={() => closePanel("grid")}
        position="right"
        width={320}
        height={400}
        autoHeight={true}
      >
        <GridPanel
          gridSettings={layout.gridSettings || { columns: 12, gap: 16, padding: 16, snapToGrid: true, showGrid: true }}
          onGridSettingsChange={updateGridSettings}
          onResetGrid={() => {
            const defaultSettings = { columns: 12, gap: 16, padding: 16, snapToGrid: true, showGrid: true };
            updateGridSettings(defaultSettings);
          }}
          onForceGridUpdate={handleForceGridUpdate}
          screenResolution={screenResolution}
        />
      </FloatingPanel>

      <FloatingPanel
        id="detailSettings"
        title="상세 설정"
        isOpen={panelStates.detailSettings?.isOpen || false}
        onClose={() => closePanel("detailSettings")}
        position="right"
        width={400}
        height={400}
        autoHeight={true}
      >
        <DetailSettingsPanel
          key={`detail-settings-${selectedComponent?.id}-${selectedComponent?.type === "widget" ? (selectedComponent as any).widgetType : "non-widget"}`}
          selectedComponent={selectedComponent || undefined}
          onUpdateProperty={(componentId: string, path: string, value: any) => {
            updateComponentProperty(componentId, path, value);
          }}
          currentTable={tables.length > 0 ? tables[0] : undefined}
          currentTableName={selectedScreen?.tableName}
        />
      </FloatingPanel>

      <FloatingPanel
        id="resolution"
        title="해상도 설정"
        isOpen={panelStates.resolution?.isOpen || false}
        onClose={() => closePanel("resolution")}
        position="right"
        width={320}
        height={400}
        autoHeight={true}
      >
        <div className="p-4">
          <ResolutionPanel currentResolution={screenResolution} onResolutionChange={handleResolutionChange} />
        </div>
      </FloatingPanel>

      {/* 그룹 생성 툴바 (필요시) */}
      {false && groupState.selectedComponents.length > 1 && (
        <div className="fixed bottom-4 left-1/2 z-50 -translate-x-1/2 transform">
          <GroupingToolbar
            selectedComponents={layout.components.filter((comp) => groupState.selectedComponents.includes(comp.id))}
            allComponents={layout.components}
            groupState={groupState}
            onGroupStateChange={setGroupState}
            onGroupCreate={(componentIds: string[], title: string, style?: any) => {
              handleGroupCreate(componentIds, title, style);
            }}
            onGroupUngroup={() => {
              // TODO: 그룹 해제 구현
            }}
            showCreateDialog={showGroupCreateDialog}
            onShowCreateDialogChange={setShowGroupCreateDialog}
          />
        </div>
      )}

      {/* 메뉴 할당 모달 */}
      <MenuAssignmentModal
        isOpen={showMenuAssignmentModal}
        onClose={() => setShowMenuAssignmentModal(false)}
        screenInfo={selectedScreen}
        onAssignmentComplete={() => {
          console.log("메뉴 할당 완료");
          // 필요시 추가 작업 수행
        }}
        onBackToList={onBackToList}
      />
    </div>
  );
}
