"use client";

import { useState, useCallback, useEffect, useMemo, useRef } from "react";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";

import {
  Palette,
  Grid3X3,
  Type,
  Calendar,
  Hash,
  CheckSquare,
  Radio,
  Save,
  Undo,
  Redo,
  Group,
  Database,
  Trash2,
  Settings,
  ChevronDown,
  Code,
  Building,
  File,
  List,
  AlignLeft,
  ChevronRight,
  Copy,
  Clipboard,
} from "lucide-react";
import {
  ScreenDefinition,
  ComponentData,
  LayoutData,
  GroupState,
  WebType,
  TableInfo,
  GroupComponent,
} from "@/types/screen";
import { generateComponentId } from "@/lib/utils/generateId";
import {
  createGroupComponent,
  calculateBoundingBox,
  calculateRelativePositions,
  restoreAbsolutePositions,
  getGroupChildren,
} from "@/lib/utils/groupingUtils";
import { GroupingToolbar } from "./GroupingToolbar";
import { screenApi } from "@/lib/api/screen";
import { toast } from "sonner";

import StyleEditor from "./StyleEditor";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { RealtimePreview } from "./RealtimePreview";

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

export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenDesignerProps) {
  const [layout, setLayout] = useState<LayoutData>({
    components: [],
    gridSettings: { columns: 12, gap: 16, padding: 16 },
  });
  const [isSaving, setIsSaving] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
  const [selectedComponent, setSelectedComponent] = useState<ComponentData | null>(null);

  // 실행취소/다시실행을 위한 히스토리 상태
  const [history, setHistory] = useState<LayoutData[]>([
    {
      components: [],
      gridSettings: { columns: 12, gap: 16, padding: 16 },
    },
  ]);
  const [historyIndex, setHistoryIndex] = useState(0);

  // 클립보드 상태 (복사/붙여넣기용)
  const [clipboard, setClipboard] = useState<{
    type: "single" | "multiple" | "group";
    data: ComponentData[];
    offset: { x: number; y: number };
    boundingBox?: { x: number; y: number; width: number; height: number };
  } | null>(null);

  // 히스토리에 상태 저장
  const saveToHistory = useCallback(
    (newLayout: LayoutData) => {
      setHistory((prevHistory) => {
        const newHistory = prevHistory.slice(0, historyIndex + 1);
        newHistory.push(JSON.parse(JSON.stringify(newLayout))); // 깊은 복사
        return newHistory.slice(-50); // 최대 50개 히스토리 유지
      });
      setHistoryIndex((prevIndex) => Math.min(prevIndex + 1, 49));
      setHasUnsavedChanges(true); // 변경사항 표시
    },
    [historyIndex],
  );

  // 실행취소
  const undo = useCallback(() => {
    if (historyIndex > 0) {
      const newIndex = historyIndex - 1;
      setHistoryIndex(newIndex);
      setLayout(JSON.parse(JSON.stringify(history[newIndex])));
      setSelectedComponent(null); // 선택 해제
    }
  }, [historyIndex, history]);

  // 다시실행
  const redo = useCallback(() => {
    if (historyIndex < history.length - 1) {
      const newIndex = historyIndex + 1;
      setHistoryIndex(newIndex);
      setLayout(JSON.parse(JSON.stringify(history[newIndex])));
      setSelectedComponent(null); // 선택 해제
    }
  }, [historyIndex, history]);

  const [dragState, setDragState] = useState({
    isDragging: false,
    draggedComponent: null as ComponentData | null,
    draggedComponents: [] as ComponentData[], // 다중선택된 컴포넌트들
    originalPosition: { x: 0, y: 0 },
    currentPosition: { x: 0, y: 0 },
    isMultiDrag: false, // 다중 드래그 여부
    initialMouse: { x: 0, y: 0 },
    grabOffset: { x: 0, y: 0 },
  });
  const [groupState, setGroupState] = useState<GroupState>({
    isGrouping: false,
    selectedComponents: [],
    groupTarget: null,
    groupMode: "create",
  });

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

  const [tables, setTables] = useState<TableInfo[]>([]);
  const [expandedTables, setExpandedTables] = useState<Set<string>>(new Set());

  // 테이블 검색 및 페이징 상태 추가
  const [searchTerm, setSearchTerm] = useState("");
  const [currentPage, setCurrentPage] = useState(1);
  const [itemsPerPage] = useState(10);

  // 드래그 박스(마키) 다중선택 상태
  const [selectionState, setSelectionState] = useState({
    isSelecting: false,
    start: { x: 0, y: 0 },
    current: { x: 0, y: 0 },
  });

  // 선택된 컴포넌트를 항상 레이아웃 최신 값으로 참조 (좌표 실시간 반영용)
  const selectedFromLayout = useMemo(() => {
    if (!selectedComponent) return null;
    return layout.components.find((c) => c.id === selectedComponent.id) || null;
  }, [selectedComponent, layout.components]);

  // 드래그 중에는 라이브 좌표를 계산하여 속성 패널에 표시
  const liveSelectedPosition = useMemo(() => {
    if (!selectedFromLayout) return { x: 0, y: 0 };

    let x = selectedFromLayout.position.x;
    let y = selectedFromLayout.position.y;

    if (dragState.isDragging) {
      const isSelectedInMulti = groupState.selectedComponents.includes(selectedFromLayout.id);
      if (dragState.isMultiDrag && isSelectedInMulti) {
        const deltaX = dragState.currentPosition.x - dragState.initialMouse.x;
        const deltaY = dragState.currentPosition.y - dragState.initialMouse.y;
        x = selectedFromLayout.position.x + deltaX;
        y = selectedFromLayout.position.y + deltaY;
      } else if (dragState.draggedComponent?.id === selectedFromLayout.id) {
        x = dragState.currentPosition.x - dragState.grabOffset.x;
        y = dragState.currentPosition.y - dragState.grabOffset.y;
      }
    }

    return { x: Math.round(x), y: Math.round(y) };
  }, [
    selectedFromLayout,
    dragState.isDragging,
    dragState.isMultiDrag,
    dragState.currentPosition.x,
    dragState.currentPosition.y,
    dragState.initialMouse.x,
    dragState.initialMouse.y,
    dragState.grabOffset.x,
    dragState.grabOffset.y,
    groupState.selectedComponents,
  ]);

  // 컴포넌트의 절대 좌표 계산 (그룹 자식은 부모 오프셋을 누적)
  const getAbsolutePosition = useCallback(
    (comp: ComponentData) => {
      let x = comp.position.x;
      let y = comp.position.y;
      let cur: ComponentData | undefined = comp;
      while (cur.parentId) {
        const parent = layout.components.find((c) => c.id === cur!.parentId);
        if (!parent) break;
        x += parent.position.x;
        y += parent.position.y;
        cur = parent;
      }
      return { x, y };
    },
    [layout.components],
  );

  // 마키 선택 시작 (캔버스 빈 영역 마우스다운)
  const handleMarqueeStart = useCallback(
    (e: React.MouseEvent) => {
      if (dragState.isDragging) return; // 드래그 중이면 무시
      const rect = canvasRef.current?.getBoundingClientRect();
      const scrollLeft = scrollContainerRef.current?.scrollLeft || 0;
      const scrollTop = scrollContainerRef.current?.scrollTop || 0;
      const x = rect ? e.clientX - rect.left + scrollLeft : 0;
      const y = rect ? e.clientY - rect.top + scrollTop : 0;
      setSelectionState({ isSelecting: true, start: { x, y }, current: { x, y } });
      // 기존 선택 초기화 (Shift 미사용 시)
      if (!e.shiftKey) {
        setGroupState((prev) => ({ ...prev, selectedComponents: [] }));
      }
    },
    [dragState.isDragging],
  );

  // 마키 이동
  const handleMarqueeMove = useCallback(
    (e: React.MouseEvent) => {
      if (!selectionState.isSelecting) return;
      const rect = canvasRef.current?.getBoundingClientRect();
      const scrollLeft = scrollContainerRef.current?.scrollLeft || 0;
      const scrollTop = scrollContainerRef.current?.scrollTop || 0;
      const x = rect ? e.clientX - rect.left + scrollLeft : 0;
      const y = rect ? e.clientY - rect.top + scrollTop : 0;
      setSelectionState((prev) => ({ ...prev, current: { x, y } }));
    },
    [selectionState.isSelecting],
  );

  // 마키 종료 -> 영역 내 컴포넌트 선택
  const handleMarqueeEnd = useCallback(() => {
    if (!selectionState.isSelecting) return;
    const minX = Math.min(selectionState.start.x, selectionState.current.x);
    const minY = Math.min(selectionState.start.y, selectionState.current.y);
    const maxX = Math.max(selectionState.start.x, selectionState.current.x);
    const maxY = Math.max(selectionState.start.y, selectionState.current.y);

    const selectedIds = layout.components
      // 그룹 컨테이너는 제외
      .filter((c) => c.type !== "group")
      .filter((c) => {
        const abs = getAbsolutePosition(c);
        const left = abs.x;
        const top = abs.y;
        const right = abs.x + c.size.width;
        const bottom = abs.y + c.size.height;
        // 영역과 교차 여부 판단 (일부라도 겹치면 선택)
        return right >= minX && left <= maxX && bottom >= minY && top <= maxY;
      })
      .map((c) => c.id);

    setGroupState((prev) => ({
      ...prev,
      selectedComponents: Array.from(new Set([...prev.selectedComponents, ...selectedIds])),
    }));
    setSelectionState({ isSelecting: false, start: { x: 0, y: 0 }, current: { x: 0, y: 0 } });
  }, [selectionState, layout.components, getAbsolutePosition]);

  // 테이블 데이터 로드 (실제로는 API에서 가져와야 함)
  useEffect(() => {
    const fetchTables = async () => {
      try {
        const response = await fetch("http://localhost:8080/api/screen-management/tables", {
          headers: {
            Authorization: `Bearer ${localStorage.getItem("authToken")}`,
          },
        });

        if (response.ok) {
          const data = await response.json();
          if (data.success) {
            setTables(data.data);
          } else {
            console.error("테이블 조회 실패:", data.message);
            // 임시 데이터로 폴백
            setTables(getMockTables());
          }
        } else {
          console.error("테이블 조회 실패:", response.status);
          // 임시 데이터로 폴백
          setTables(getMockTables());
        }
      } catch (error) {
        console.error("테이블 조회 중 오류:", error);
        // 임시 데이터로 폴백
        setTables(getMockTables());
      }
    };

    fetchTables();
  }, []);

  // 검색된 테이블 필터링
  const filteredTables = useMemo(() => {
    if (!searchTerm.trim()) return tables;

    return tables.filter(
      (table) =>
        table.tableName.toLowerCase().includes(searchTerm.toLowerCase()) ||
        table.tableLabel.toLowerCase().includes(searchTerm.toLowerCase()) ||
        table.columns.some(
          (column) =>
            column.columnName.toLowerCase().includes(searchTerm.toLowerCase()) ||
            (column.columnLabel || column.columnName).toLowerCase().includes(searchTerm.toLowerCase()),
        ),
    );
  }, [tables, searchTerm]);

  // 페이징된 테이블
  const paginatedTables = useMemo(() => {
    const startIndex = (currentPage - 1) * itemsPerPage;
    const endIndex = startIndex + itemsPerPage;
    return filteredTables.slice(startIndex, endIndex);
  }, [filteredTables, currentPage, itemsPerPage]);

  // 총 페이지 수 계산
  const totalPages = Math.ceil(filteredTables.length / itemsPerPage);

  // 페이지 변경 핸들러
  const handlePageChange = (page: number) => {
    setCurrentPage(page);
    setExpandedTables(new Set()); // 페이지 변경 시 확장 상태 초기화
  };

  // 검색어 변경 핸들러
  const handleSearchChange = (value: string) => {
    setSearchTerm(value);
    setCurrentPage(1); // 검색 시 첫 페이지로 이동
    setExpandedTables(new Set()); // 검색 시 확장 상태 초기화
  };

  // 임시 테이블 데이터 (API 실패 시 사용)
  const getMockTables = (): TableInfo[] => [
    {
      tableName: "user_info",
      tableLabel: "사용자 정보",
      columns: [
        {
          tableName: "user_info",
          columnName: "user_id",
          columnLabel: "사용자 ID",
          webType: "text",
          dataType: "VARCHAR",
          isNullable: "NO",
        },
        {
          tableName: "user_info",
          columnName: "user_name",
          columnLabel: "사용자명",
          webType: "text",
          dataType: "VARCHAR",
          isNullable: "NO",
        },
        {
          tableName: "user_info",
          columnName: "email",
          columnLabel: "이메일",
          webType: "email",
          dataType: "VARCHAR",
          isNullable: "YES",
        },
        {
          tableName: "user_info",
          columnName: "phone",
          columnLabel: "전화번호",
          webType: "tel",
          dataType: "VARCHAR",
          isNullable: "YES",
        },
        {
          tableName: "user_info",
          columnName: "birth_date",
          columnLabel: "생년월일",
          webType: "date",
          dataType: "DATE",
          isNullable: "YES",
        },
        {
          tableName: "user_info",
          columnName: "is_active",
          columnLabel: "활성화",
          webType: "checkbox",
          dataType: "BOOLEAN",
          isNullable: "NO",
        },
        {
          tableName: "user_info",
          columnName: "profile_code",
          columnLabel: "프로필 코드",
          webType: "code",
          dataType: "TEXT",
          isNullable: "YES",
        },
        {
          tableName: "user_info",
          columnName: "department",
          columnLabel: "부서",
          webType: "entity",
          dataType: "VARCHAR",
          isNullable: "YES",
        },
        {
          tableName: "user_info",
          columnName: "profile_image",
          columnLabel: "프로필 이미지",
          webType: "file",
          dataType: "VARCHAR",
          isNullable: "YES",
        },
      ],
    },
    {
      tableName: "product_info",
      tableLabel: "제품 정보",
      columns: [
        {
          tableName: "product_info",
          columnName: "product_id",
          columnLabel: "제품 ID",
          webType: "text",
          dataType: "VARCHAR",
          isNullable: "NO",
        },
        {
          tableName: "product_info",
          columnName: "product_name",
          columnLabel: "제품명",
          webType: "text",
          dataType: "VARCHAR",
          isNullable: "NO",
        },
        {
          tableName: "product_info",
          columnName: "category",
          columnLabel: "카테고리",
          webType: "select",
          dataType: "VARCHAR",
          isNullable: "YES",
        },
        {
          tableName: "product_info",
          columnName: "price",
          columnLabel: "가격",
          webType: "number",
          dataType: "DECIMAL",
          isNullable: "YES",
        },
        {
          tableName: "product_info",
          columnName: "description",
          columnLabel: "설명",
          webType: "textarea",
          dataType: "TEXT",
          isNullable: "YES",
        },
        {
          tableName: "product_info",
          columnName: "created_date",
          columnLabel: "생성일",
          webType: "date",
          dataType: "TIMESTAMP",
          isNullable: "NO",
        },
      ],
    },
    {
      tableName: "order_info",
      tableLabel: "주문 정보",
      columns: [
        {
          tableName: "order_info",
          columnName: "order_id",
          columnLabel: "주문 ID",
          webType: "text",
          dataType: "VARCHAR",
          isNullable: "NO",
        },
        {
          tableName: "order_info",
          columnName: "customer_name",
          columnLabel: "고객명",
          webType: "text",
          dataType: "VARCHAR",
          isNullable: "NO",
        },
        {
          tableName: "order_info",
          columnName: "order_date",
          columnLabel: "주문일",
          webType: "date",
          dataType: "DATE",
          isNullable: "NO",
        },
        {
          tableName: "order_info",
          columnName: "total_amount",
          columnLabel: "총 금액",
          webType: "number",
          dataType: "DECIMAL",
          isNullable: "NO",
        },
        {
          tableName: "order_info",
          columnName: "status",
          columnLabel: "상태",
          webType: "select",
          dataType: "VARCHAR",
          isNullable: "NO",
        },
        {
          tableName: "order_info",
          columnName: "notes",
          columnLabel: "비고",
          webType: "textarea",
          dataType: "TEXT",
          isNullable: "YES",
        },
      ],
    },
  ];

  // 테이블 확장/축소 토글
  const toggleTableExpansion = useCallback((tableName: string) => {
    setExpandedTables((prev) => {
      const newSet = new Set(prev);
      if (newSet.has(tableName)) {
        newSet.delete(tableName);
      } else {
        newSet.add(tableName);
      }
      return newSet;
    });
  }, []);

  // 웹타입에 따른 위젯 타입 매핑
  const getWidgetTypeFromWebType = useCallback((webType: string): string => {
    console.log("getWidgetTypeFromWebType - input webType:", webType);
    switch (webType) {
      case "text":
        return "text";
      case "email":
        return "email";
      case "tel":
        return "tel";
      case "number":
        return "number";
      case "decimal":
        return "decimal";
      case "date":
        return "date";
      case "datetime":
        return "datetime";
      case "select":
        return "select";
      case "dropdown":
        return "dropdown";
      case "textarea":
        return "textarea";
      case "text_area":
        return "text_area";
      case "checkbox":
        return "checkbox";
      case "boolean":
        return "boolean";
      case "radio":
        return "radio";
      case "code":
        return "code";
      case "entity":
        return "entity";
      case "file":
        return "file";
      default:
        console.log("getWidgetTypeFromWebType - default case, returning text for:", webType);
        return "text";
    }
  }, []);

  // 범용 복사 함수
  const copyComponents = useCallback(() => {
    if (!selectedComponent && groupState.selectedComponents.length === 0) return;

    let componentsToCopy: ComponentData[] = [];
    let copyType: "single" | "multiple" | "group" = "single";

    if (selectedComponent?.type === "group") {
      // 그룹 복사
      const children = getGroupChildren(layout.components, selectedComponent.id);
      componentsToCopy = [selectedComponent, ...children];
      copyType = "group";
    } else if (groupState.selectedComponents.length > 1) {
      // 다중 선택 복사
      componentsToCopy = layout.components.filter((comp) => groupState.selectedComponents.includes(comp.id));
      copyType = "multiple";
    } else if (selectedComponent) {
      // 단일 컴포넌트 복사
      componentsToCopy = [selectedComponent];
      copyType = "single";
    }

    if (componentsToCopy.length === 0) return;

    // 바운딩 박스 계산
    const positions = componentsToCopy.map((comp) => ({
      x: comp.position.x,
      y: comp.position.y,
      width: comp.size.width,
      height: comp.size.height,
    }));

    const minX = Math.min(...positions.map((p) => p.x));
    const minY = Math.min(...positions.map((p) => p.y));
    const maxX = Math.max(...positions.map((p) => p.x + p.width));
    const maxY = Math.max(...positions.map((p) => p.y + p.height));

    setClipboard({
      type: copyType,
      data: componentsToCopy,
      offset: { x: 20, y: 20 },
      boundingBox: { x: minX, y: minY, width: maxX - minX, height: maxY - minY },
    });
  }, [selectedComponent, groupState.selectedComponents, layout.components]);

  // 범용 삭제 함수
  const deleteComponents = useCallback(() => {
    if (!selectedComponent && groupState.selectedComponents.length === 0) return;

    let idsToRemove: string[] = [];

    if (selectedComponent?.type === "group") {
      // 그룹 삭제 (자식 컴포넌트 포함)
      const childrenIds = getGroupChildren(layout.components, selectedComponent.id).map((child) => child.id);
      idsToRemove = [selectedComponent.id, ...childrenIds];
    } else if (groupState.selectedComponents.length > 1) {
      // 다중 선택 삭제
      idsToRemove = [...groupState.selectedComponents];
    } else if (selectedComponent) {
      // 단일 컴포넌트 삭제
      idsToRemove = [selectedComponent.id];
    }

    if (idsToRemove.length === 0) return;

    const newLayout = {
      ...layout,
      components: layout.components.filter((comp) => !idsToRemove.includes(comp.id)),
    };
    setLayout(newLayout);
    saveToHistory(newLayout);

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

  // 범용 붙여넣기 함수
  const pasteComponents = useCallback(
    (pastePosition?: { x: number; y: number }) => {
      if (!clipboard || clipboard.data.length === 0) return;

      const idMap = new Map<string, string>();
      const newComponents: ComponentData[] = [];

      // 붙여넣기 위치 결정
      let targetPosition = pastePosition;
      if (!targetPosition && clipboard.boundingBox) {
        targetPosition = {
          x: clipboard.boundingBox.x + clipboard.offset.x,
          y: clipboard.boundingBox.y + clipboard.offset.y,
        };
      }

      const offsetX = targetPosition ? targetPosition.x - (clipboard.boundingBox?.x || 0) : clipboard.offset.x;
      const offsetY = targetPosition ? targetPosition.y - (clipboard.boundingBox?.y || 0) : clipboard.offset.y;

      // 모든 컴포넌트에 대해 새 ID 생성
      clipboard.data.forEach((comp) => {
        const newId = generateComponentId();
        idMap.set(comp.id, newId);
      });

      // 컴포넌트 복사 및 ID/위치 업데이트
      clipboard.data.forEach((comp) => {
        const newComp: ComponentData = {
          ...comp,
          id: idMap.get(comp.id)!,
          position: {
            x: comp.position.x + offsetX,
            y: comp.position.y + offsetY,
          },
          // 부모 ID가 있고 매핑되는 경우 업데이트
          parentId: comp.parentId && idMap.has(comp.parentId) ? idMap.get(comp.parentId)! : undefined,
        };
        newComponents.push(newComp);
      });

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

  // 캔버스 우클릭 컨텍스트 메뉴
  const handleCanvasContextMenu = useCallback(
    (e: React.MouseEvent) => {
      e.preventDefault();
      // 우클릭 시 붙여넣기 (클립보드에 데이터가 있는 경우)
      if (clipboard && clipboard.data.length > 0) {
        const rect = e.currentTarget.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        pasteComponents({ x, y });
      }
    },
    [clipboard, pasteComponents],
  );

  // 키보드 단축키 지원
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.ctrlKey || e.metaKey) {
        switch (e.key) {
          case "z":
            e.preventDefault();
            if (e.shiftKey) {
              redo(); // Ctrl+Shift+Z 또는 Cmd+Shift+Z
            } else {
              undo(); // Ctrl+Z 또는 Cmd+Z
            }
            break;
          case "y":
            e.preventDefault();
            redo(); // Ctrl+Y 또는 Cmd+Y
            break;
          case "c":
            e.preventDefault();
            // 선택된 컴포넌트(들) 복사
            copyComponents();
            break;
          case "v":
            e.preventDefault();
            // 클립보드 내용 붙여넣기
            if (clipboard && clipboard.data.length > 0) {
              pasteComponents();
            }
            break;
          case "g":
          case "G":
            e.preventDefault();
            if (e.shiftKey) {
              // Ctrl+Shift+G: 그룹 해제
              const selectedComponents = layout.components.filter((comp) =>
                groupState.selectedComponents.includes(comp.id),
              );
              if (selectedComponents.length === 1 && selectedComponents[0].type === "group") {
                // 그룹 해제 로직을 직접 실행
                const group = selectedComponents[0] as any;
                const groupChildren = layout.components.filter((comp) => comp.parentId === group.id);

                // 자식 컴포넌트들의 절대 위치 복원
                const absoluteChildren = groupChildren.map((child) => ({
                  ...child,
                  position: {
                    ...child.position,
                    x: child.position.x + group.position.x,
                    y: child.position.y + group.position.y,
                    z: child.position.z || 1,
                  },
                  parentId: undefined,
                }));

                const newLayout = {
                  ...layout,
                  components: [
                    ...layout.components.filter((comp) => comp.id !== group.id && comp.parentId !== group.id),
                    ...absoluteChildren,
                  ],
                };

                setLayout(newLayout);
                saveToHistory(newLayout);
                setGroupState((prev) => ({
                  ...prev,
                  selectedComponents: [],
                  isGrouping: false,
                }));
              }
            } else {
              // Ctrl+G: 그룹 생성 다이얼로그 열기
              const selectedComponents = layout.components.filter((comp) =>
                groupState.selectedComponents.includes(comp.id),
              );
              if (selectedComponents.length >= 2) {
                setShowGroupCreateDialog(true);
              }
            }
            break;
        }
      } else if (e.key === "Delete") {
        e.preventDefault();
        // 선택된 컴포넌트(들) 삭제
        deleteComponents();
      }
    };

    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [
    undo,
    redo,
    copyComponents,
    pasteComponents,
    deleteComponents,
    clipboard,
    layout,
    groupState,
    saveToHistory,
    setLayout,
    setGroupState,
    setShowGroupCreateDialog,
  ]);

  // 컴포넌트 속성 업데이트 함수
  const updateComponentProperty = useCallback(
    (componentId: string, propertyPath: string, value: any) => {
      const newLayout = {
        ...layout,
        components: layout.components.map((comp) => {
          if (comp.id === componentId) {
            const newComp = { ...comp };
            const pathParts = propertyPath.split(".");
            let current: any = newComp;

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

            return newComp;
          }
          return comp;
        }),
      };
      setLayout(newLayout);
      saveToHistory(newLayout);
      // 선택된 컴포넌트인 경우 즉시 상태도 동기화하여 입력 즉시 반영되도록 처리
      if (selectedComponent && selectedComponent.id === componentId) {
        const updated = newLayout.components.find((c) => c.id === componentId) || null;
        if (updated) setSelectedComponent(updated);
      }
    },
    [layout, saveToHistory, selectedComponent],
  );

  // 그룹 생성 함수
  const handleGroupCreate = useCallback(
    (componentIds: string[], title: string, style?: any) => {
      const selectedComponents = layout.components.filter((comp) => componentIds.includes(comp.id));

      if (selectedComponents.length < 2) {
        return;
      }

      // 경계 박스 계산
      const boundingBox = calculateBoundingBox(selectedComponents);

      // 그룹 컴포넌트 생성 (경계 박스 정보 전달)
      const groupComponent = createGroupComponent(
        componentIds,
        title,
        { x: boundingBox.minX, y: boundingBox.minY },
        { width: boundingBox.width, height: boundingBox.height },
        style,
      );

      // 자식 컴포넌트들의 상대 위치 계산
      const relativeChildren = calculateRelativePositions(
        selectedComponents,
        {
          x: boundingBox.minX,
          y: boundingBox.minY,
        },
        groupComponent.id,
      );

      // 새 레이아웃 생성
      const newLayout = {
        ...layout,
        components: [
          // 그룹에 포함되지 않은 기존 컴포넌트들만 유지
          ...layout.components.filter((comp) => !componentIds.includes(comp.id)),
          // 그룹 컴포넌트 추가
          groupComponent,
          // 자식 컴포넌트들도 유지 (parentId로 그룹과 연결)
          ...relativeChildren,
        ],
      };

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

  // 그룹 해제 함수
  const handleGroupUngroup = useCallback(
    (groupId: string) => {
      const group = layout.components.find((comp) => comp.id === groupId) as GroupComponent;
      if (!group || group.type !== "group") {
        return;
      }

      const groupChildren = getGroupChildren(layout.components, groupId);

      // 자식 컴포넌트들의 절대 위치 복원
      const absoluteChildren = restoreAbsolutePositions(groupChildren, group.position);

      // 새 레이아웃 생성
      const newLayout = {
        ...layout,
        components: [
          // 그룹과 그룹의 자식 컴포넌트들을 제외한 기존 컴포넌트들
          ...layout.components.filter((comp) => comp.id !== groupId && comp.parentId !== groupId),
          // 절대 위치로 복원된 자식 컴포넌트들
          ...absoluteChildren,
        ],
      };

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

  // 레이아웃 저장 함수
  const saveLayout = useCallback(async () => {
    if (!selectedScreen) {
      toast.error("저장할 화면이 선택되지 않았습니다.");
      return;
    }

    try {
      setIsSaving(true);
      await screenApi.saveLayout(selectedScreen.screenId, layout);
      setHasUnsavedChanges(false); // 저장 완료 시 변경사항 플래그 해제
      toast.success("레이아웃이 성공적으로 저장되었습니다.");
    } catch (error) {
      console.error("레이아웃 저장 실패:", error);
      toast.error("레이아웃 저장에 실패했습니다.");
    } finally {
      setIsSaving(false);
    }
  }, [layout, selectedScreen]);

  // 레이아웃 로드 함수
  const loadLayout = useCallback(async () => {
    if (!selectedScreen) return;

    try {
      setIsLoading(true);
      const savedLayout = await screenApi.getLayout(selectedScreen.screenId);

      if (savedLayout && savedLayout.components) {
        setLayout(savedLayout);
        // 히스토리 초기화
        setHistory([savedLayout]);
        setHistoryIndex(0);
        setHasUnsavedChanges(false); // 로드 완료 시 변경사항 플래그 해제
        toast.success("레이아웃을 불러왔습니다.");
      } else {
        // 저장된 레이아웃이 없는 경우 기본 레이아웃 유지
        const defaultLayout = {
          components: [],
          gridSettings: { columns: 12, gap: 16, padding: 16 },
        };
        setLayout(defaultLayout);
        setHistory([defaultLayout]);
        setHistoryIndex(0);
        setHasUnsavedChanges(false);
      }
    } catch (error) {
      console.error("레이아웃 로드 실패:", error);
      // 에러 시에도 기본 레이아웃으로 초기화
      const defaultLayout = {
        components: [],
        gridSettings: { columns: 12, gap: 16, padding: 16 },
      };
      setLayout(defaultLayout);
      setHistory([defaultLayout]);
      setHistoryIndex(0);
      setHasUnsavedChanges(false);
      toast.error("레이아웃 로드에 실패했습니다. 새 레이아웃으로 시작합니다.");
    } finally {
      setIsLoading(false);
    }
  }, [selectedScreen]);

  // 화면 선택 시 레이아웃 로드
  useEffect(() => {
    if (selectedScreen) {
      loadLayout();
    }
  }, [selectedScreen, loadLayout]);

  // 캔버스 참조 (좌표 계산 정확도 향상)
  const canvasRef = useRef<HTMLDivElement | null>(null);
  const scrollContainerRef = useRef<HTMLDivElement | null>(null);

  // 드래그 시작 (새 컴포넌트 추가)
  const startDrag = useCallback((component: Partial<ComponentData>, e: React.DragEvent) => {
    const canvasRect = canvasRef.current?.getBoundingClientRect();
    const scrollLeft = scrollContainerRef.current?.scrollLeft || 0;
    const scrollTop = scrollContainerRef.current?.scrollTop || 0;
    const relMouseX = (canvasRect ? e.clientX - canvasRect.left : 0) + scrollLeft;
    const relMouseY = (canvasRect ? e.clientY - canvasRect.top : 0) + scrollTop;

    setDragState({
      isDragging: true,
      draggedComponent: component as ComponentData,
      draggedComponents: [component as ComponentData],
      originalPosition: { x: 0, y: 0 },
      currentPosition: { x: relMouseX, y: relMouseY },
      isMultiDrag: false,
      initialMouse: { x: relMouseX, y: relMouseY },
      grabOffset: { x: 0, y: 0 },
    });
    e.dataTransfer.setData("application/json", JSON.stringify(component));
  }, []);

  // 기존 컴포넌트 드래그 시작 (재배치)
  const startComponentDrag = useCallback(
    (component: ComponentData, e: React.DragEvent) => {
      e.stopPropagation();

      // 다중선택된 컴포넌트들이 있는지 확인
      const selectedComponents = layout.components.filter((comp) => groupState.selectedComponents.includes(comp.id));

      const isMultiDrag = selectedComponents.length > 1 && groupState.selectedComponents.includes(component.id);

      // 마우스-컴포넌트 그랩 오프셋 계산 (커서와 컴포넌트 좌측상단의 거리)
      const canvasRect = canvasRef.current?.getBoundingClientRect();
      const scrollLeft = scrollContainerRef.current?.scrollLeft || 0;
      const scrollTop = scrollContainerRef.current?.scrollTop || 0;
      const relMouseX = (canvasRect ? e.clientX - canvasRect.left : 0) + scrollLeft;
      const relMouseY = (canvasRect ? e.clientY - canvasRect.top : 0) + scrollTop;
      const grabOffsetX = relMouseX - component.position.x;
      const grabOffsetY = relMouseY - component.position.y;

      if (isMultiDrag) {
        // 다중 드래그
        setDragState({
          isDragging: true,
          draggedComponent: component,
          draggedComponents: selectedComponents,
          originalPosition: component.position,
          currentPosition: { x: relMouseX, y: relMouseY },
          isMultiDrag: true,
          initialMouse: { x: relMouseX, y: relMouseY },
          grabOffset: { x: grabOffsetX, y: grabOffsetY },
        });
        e.dataTransfer.setData(
          "application/json",
          JSON.stringify({
            ...component,
            isMoving: true,
            isMultiDrag: true,
            selectedComponentIds: groupState.selectedComponents,
          }),
        );
      } else {
        // 단일 드래그
        setDragState({
          isDragging: true,
          draggedComponent: component,
          draggedComponents: [component],
          originalPosition: component.position,
          currentPosition: { x: relMouseX, y: relMouseY },
          isMultiDrag: false,
          initialMouse: { x: relMouseX, y: relMouseY },
          grabOffset: { x: grabOffsetX, y: grabOffsetY },
        });
        e.dataTransfer.setData("application/json", JSON.stringify({ ...component, isMoving: true }));
      }
    },
    [layout.components, groupState.selectedComponents],
  );

  // 드래그 중
  const onDragOver = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();
      if (dragState.isDragging) {
        const rect = canvasRef.current?.getBoundingClientRect();
        // 스크롤 오프셋 추가하여 컨텐츠 좌표로 변환 (상위 스크롤 컨테이너 기준)
        const scrollLeft = scrollContainerRef.current?.scrollLeft || 0;
        const scrollTop = scrollContainerRef.current?.scrollTop || 0;
        const x = rect ? e.clientX - rect.left + scrollLeft : 0;
        const y = rect ? e.clientY - rect.top + scrollTop : 0;

        setDragState((prev) => ({
          ...prev,
          currentPosition: { x, y },
        }));
      }
    },
    [dragState.isDragging],
  );

  // 드롭 처리
  const onDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();

      try {
        const data = JSON.parse(e.dataTransfer.getData("application/json"));

        if (data.isMoving) {
          // 기존 컴포넌트 재배치
          const rect = canvasRef.current?.getBoundingClientRect();
          // 스크롤 오프셋 추가하여 컨텐츠 좌표로 변환 (상위 스크롤 컨테이너 기준)
          const scrollLeft = scrollContainerRef.current?.scrollLeft || 0;
          const scrollTop = scrollContainerRef.current?.scrollTop || 0;
          const mouseX = rect ? e.clientX - rect.left + scrollLeft : 0;
          const mouseY = rect ? e.clientY - rect.top + scrollTop : 0;

          if (data.isMultiDrag && data.selectedComponentIds) {
            // 다중 드래그 처리
            // 그랩한 컴포넌트의 시작 위치 기준 델타 계산 (그랩 오프셋 반영)
            const dropX = mouseX - dragState.grabOffset.x;
            const dropY = mouseY - dragState.grabOffset.y;
            const deltaX = dropX - dragState.originalPosition.x;
            const deltaY = dropY - dragState.originalPosition.y;

            const newLayout = {
              ...layout,
              components: layout.components.map((comp) => {
                if (data.selectedComponentIds.includes(comp.id)) {
                  return {
                    ...comp,
                    position: {
                      x: comp.position.x + deltaX,
                      y: comp.position.y + deltaY,
                    },
                  };
                }
                return comp;
              }),
            };
            setLayout(newLayout);
            saveToHistory(newLayout);
          } else {
            // 단일 드래그 처리
            const x = mouseX - dragState.grabOffset.x;
            const y = mouseY - dragState.grabOffset.y;
            const newLayout = {
              ...layout,
              components: layout.components.map((comp) =>
                comp.id === data.id ? { ...comp, position: { x, y } } : comp,
              ),
            };
            setLayout(newLayout);
            saveToHistory(newLayout);
          }
        } else {
          // 새 컴포넌트 추가
          const rect = canvasRef.current?.getBoundingClientRect();
          // 스크롤 오프셋 추가하여 컨텐츠 좌표로 변환 (상위 스크롤 컨테이너 기준)
          const scrollLeft = scrollContainerRef.current?.scrollLeft || 0;
          const scrollTop = scrollContainerRef.current?.scrollTop || 0;
          const x = rect ? e.clientX - rect.left + scrollLeft : 0;
          const y = rect ? e.clientY - rect.top + scrollTop : 0;

          const newComponent: ComponentData = {
            ...data,
            id: generateComponentId(),
            position: { x, y },
          } as ComponentData;

          const newLayout = {
            ...layout,
            components: [...layout.components, newComponent],
          };
          setLayout(newLayout);
          saveToHistory(newLayout);
        }
      } catch (error) {
        console.error("드롭 처리 중 오류:", error);
      }

      setDragState({
        isDragging: false,
        draggedComponent: null,
        draggedComponents: [],
        originalPosition: { x: 0, y: 0 },
        currentPosition: { x: 0, y: 0 },
        isMultiDrag: false,
        initialMouse: { x: 0, y: 0 },
        grabOffset: { x: 0, y: 0 },
      });
    },
    [
      layout,
      saveToHistory,
      dragState.initialMouse.x,
      dragState.initialMouse.y,
      dragState.grabOffset.x,
      dragState.grabOffset.y,
    ],
  );

  // 드래그 종료
  const endDrag = useCallback(() => {
    setDragState({
      isDragging: false,
      draggedComponent: null,
      draggedComponents: [],
      originalPosition: { x: 0, y: 0 },
      currentPosition: { x: 0, y: 0 },
      isMultiDrag: false,
      initialMouse: { x: 0, y: 0 },
      grabOffset: { x: 0, y: 0 },
    });
  }, []);

  // 컴포넌트 클릭 (선택)
  const handleComponentClick = useCallback(
    (component: ComponentData, event?: React.MouseEvent) => {
      const isShiftPressed = event?.shiftKey || false;
      const isGroupContainer = component.type === "group";

      if (groupState.isGrouping || isShiftPressed) {
        // 그룹화 모드이거나 시프트 키를 누른 경우 다중 선택
        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 (isShiftPressed) {
          setSelectedComponent(component);
        }
      } else {
        // 일반 모드에서는 단일 선택
        setSelectedComponent(component);
        setGroupState((prev) => ({
          ...prev,
          selectedComponents: [component.id], // 그룹도 선택 가능하도록 수정
        }));
      }
    },
    [groupState.isGrouping, groupState.selectedComponents],
  );

  // 화면이 선택되지 않았을 때 처리
  if (!selectedScreen) {
    return (
      <div className="flex h-full items-center justify-center">
        <div className="text-center text-gray-500">
          <Palette className="mx-auto mb-4 h-16 w-16 text-gray-300" />
          <p className="mb-4 text-lg">설계할 화면을 선택해주세요</p>
          <p className="mb-6 text-sm">화면 목록에서 화면을 선택한 후 설계기를 사용하세요</p>
          <Button onClick={onBackToList} variant="outline">
            화면 목록으로 돌아가기
          </Button>
        </div>
      </div>
    );
  }

  return (
    <div className="flex h-full w-full flex-col">
      {/* 상단 헤더 */}
      <div className="flex items-center justify-between border-b bg-white p-4 shadow-sm">
        <div className="flex items-center space-x-4">
          <h2 className="text-xl font-semibold text-gray-900">
            {selectedScreen.screenName} - 화면 설계
            {isLoading && <span className="ml-2 text-sm text-gray-500">(로딩 중...)</span>}
          </h2>
          <Badge variant="outline" className="font-mono">
            {selectedScreen.tableName}
          </Badge>
          {clipboard && clipboard.data.length > 0 && (
            <Badge variant="secondary" className="text-xs">
              <Clipboard className="mr-1 h-3 w-3" />
              {clipboard.type === "group"
                ? "그룹 복사됨"
                : clipboard.type === "multiple"
                  ? `${clipboard.data.length}개 복사됨`
                  : "컴포넌트 복사됨"}
            </Badge>
          )}
        </div>
        <div className="flex items-center space-x-2">
          <Button
            variant={groupState.isGrouping ? "default" : "outline"}
            size="sm"
            onClick={() => setGroupState((prev) => ({ ...prev, isGrouping: !prev.isGrouping }))}
            title="그룹화 모드 토글 (일반 모드에서도 Shift+클릭으로 다중선택 가능)"
          >
            <Group className="mr-2 h-4 w-4" />
            {groupState.isGrouping ? "그룹화 모드" : "일반 모드"}
          </Button>

          {/* 복사/붙여넣기/삭제 버튼들 */}
          {(selectedComponent || groupState.selectedComponents.length > 0) && (
            <>
              <Button variant="outline" size="sm" onClick={copyComponents} title="복사 (Ctrl+C)">
                <Copy className="mr-2 h-4 w-4" />
                복사
              </Button>
              <Button variant="destructive" size="sm" onClick={deleteComponents} title="삭제 (Delete 키)">
                <Trash2 className="mr-2 h-4 w-4" />
                삭제
              </Button>
            </>
          )}

          {/* 붙여넣기 버튼 */}
          {clipboard && clipboard.data.length > 0 && (
            <Button variant="outline" size="sm" onClick={() => pasteComponents()} title="붙여넣기 (Ctrl+V)">
              <Clipboard className="mr-2 h-4 w-4" />
              붙여넣기
            </Button>
          )}

          <Button variant="outline" size="sm" onClick={undo} disabled={historyIndex <= 0} title="실행 취소 (Ctrl+Z)">
            <Undo className="mr-2 h-4 w-4" />
            실행 취소
          </Button>
          <Button
            variant="outline"
            size="sm"
            onClick={redo}
            disabled={historyIndex >= history.length - 1}
            title="다시 실행 (Ctrl+Y)"
          >
            <Redo className="mr-2 h-4 w-4" />
            다시 실행
          </Button>
          <Button
            onClick={saveLayout}
            disabled={isSaving || !selectedScreen}
            className={`${hasUnsavedChanges ? "bg-orange-600 hover:bg-orange-700" : "bg-blue-600 hover:bg-blue-700"}`}
          >
            <Save className="mr-2 h-4 w-4" />
            {isSaving ? "저장 중..." : hasUnsavedChanges ? "저장 *" : "저장"}
          </Button>
        </div>
      </div>

      {/* 그룹화 툴바 */}
      <GroupingToolbar
        groupState={groupState}
        onGroupStateChange={setGroupState}
        onGroupCreate={handleGroupCreate}
        onGroupUngroup={handleGroupUngroup}
        selectedComponents={layout.components.filter((comp) => groupState.selectedComponents.includes(comp.id))}
        allComponents={layout.components}
        onGroupAlign={(mode) => {
          const selected = layout.components.filter((c) => groupState.selectedComponents.includes(c.id));
          if (selected.length < 2) return;

          let newComponents = [...layout.components];
          const minX = Math.min(...selected.map((c) => c.position.x));
          const maxX = Math.max(...selected.map((c) => c.position.x + c.size.width));
          const minY = Math.min(...selected.map((c) => c.position.y));
          const maxY = Math.max(...selected.map((c) => c.position.y + c.size.height));
          const centerX = (minX + maxX) / 2;
          const centerY = (minY + maxY) / 2;

          newComponents = newComponents.map((c) => {
            if (!groupState.selectedComponents.includes(c.id)) return c;
            if (mode === "left") return { ...c, position: { x: minX, y: c.position.y } };
            if (mode === "right") return { ...c, position: { x: maxX - c.size.width, y: c.position.y } };
            if (mode === "centerX")
              return { ...c, position: { x: Math.round(centerX - c.size.width / 2), y: c.position.y } };
            if (mode === "top") return { ...c, position: { x: c.position.x, y: minY } };
            if (mode === "bottom") return { ...c, position: { x: c.position.x, y: maxY - c.size.height } };
            if (mode === "centerY")
              return { ...c, position: { x: c.position.x, y: Math.round(centerY - c.size.height / 2) } };
            return c;
          });

          const newLayout = { ...layout, components: newComponents };
          setLayout(newLayout);
          saveToHistory(newLayout);
        }}
        onGroupDistribute={(orientation) => {
          const selected = layout.components.filter((c) => groupState.selectedComponents.includes(c.id));
          if (selected.length < 3) return; // 균등 분배는 3개 이상 권장

          const sorted = [...selected].sort((a, b) =>
            orientation === "horizontal" ? a.position.x - b.position.x : a.position.y - b.position.y,
          );

          if (orientation === "horizontal") {
            const left = sorted[0].position.x;
            const right = Math.max(...sorted.map((c) => c.position.x + c.size.width));
            const totalWidth = right - left;
            const gaps = sorted.length - 1;
            const usedWidth = sorted.reduce((sum, c) => sum + c.size.width, 0);
            const gapSize = gaps > 0 ? Math.max(0, Math.round((totalWidth - usedWidth) / gaps)) : 0;

            let cursor = left;
            sorted.forEach((c, idx) => {
              c.position.x = cursor;
              cursor += c.size.width + gapSize;
            });
          } else {
            const top = sorted[0].position.y;
            const bottom = Math.max(...sorted.map((c) => c.position.y + c.size.height));
            const totalHeight = bottom - top;
            const gaps = sorted.length - 1;
            const usedHeight = sorted.reduce((sum, c) => sum + c.size.height, 0);
            const gapSize = gaps > 0 ? Math.max(0, Math.round((totalHeight - usedHeight) / gaps)) : 0;

            let cursor = top;
            sorted.forEach((c, idx) => {
              c.position.y = cursor;
              cursor += c.size.height + gapSize;
            });
          }

          const newLayout = { ...layout, components: [...layout.components] };
          setLayout(newLayout);
          saveToHistory(newLayout);
        }}
        showCreateDialog={showGroupCreateDialog}
        onShowCreateDialogChange={setShowGroupCreateDialog}
      />

      {/* 메인 컨텐츠 영역 */}
      <div className="flex flex-1 overflow-hidden">
        {/* 좌측 사이드바 - 테이블 타입 */}
        <div className="flex w-80 flex-col border-r bg-gray-50">
          <div className="border-b bg-white p-4">
            <h3 className="mb-4 text-lg font-medium">테이블 타입</h3>

            {/* 검색 입력창 */}
            <div className="mb-4">
              <input
                type="text"
                placeholder="테이블명, 컬럼명으로 검색..."
                value={searchTerm}
                onChange={(e) => handleSearchChange(e.target.value)}
                className="w-full rounded-md border border-gray-300 px-3 py-2 focus:border-transparent focus:ring-2 focus:ring-blue-500 focus:outline-none"
              />
            </div>

            {/* 검색 결과 정보 */}
            <div className="mb-2 text-sm text-gray-600">
              총 {filteredTables.length}개 테이블 중 {(currentPage - 1) * itemsPerPage + 1}-
              {Math.min(currentPage * itemsPerPage, filteredTables.length)}번째
            </div>

            <p className="mb-4 text-sm text-gray-600">테이블과 컬럼을 드래그하여 캔버스에 배치하세요.</p>
          </div>

          {/* 테이블 목록 */}
          <div className="flex-1 overflow-y-auto">
            {paginatedTables.map((table) => (
              <div key={table.tableName} className="border-b bg-white">
                {/* 테이블 헤더 */}
                <div
                  className="flex cursor-pointer items-center justify-between p-3 hover:bg-gray-100"
                  draggable
                  onDragStart={(e) =>
                    startDrag(
                      {
                        type: "container",
                        tableName: table.tableName,
                        label: table.tableLabel,
                        size: { width: 200, height: 80 }, // 픽셀 단위로 변경
                      },
                      e,
                    )
                  }
                >
                  <div className="flex items-center space-x-2">
                    <Database className="h-4 w-4 text-blue-600" />
                    <div>
                      <div className="text-sm font-medium">{table.tableLabel}</div>
                      <div className="text-xs text-gray-500">{table.tableName}</div>
                    </div>
                  </div>
                  <Button
                    variant="ghost"
                    size="sm"
                    onClick={() => toggleTableExpansion(table.tableName)}
                    className="h-6 w-6 p-0"
                  >
                    {expandedTables.has(table.tableName) ? (
                      <ChevronDown className="h-4 w-4" />
                    ) : (
                      <ChevronRight className="h-4 w-4" />
                    )}
                  </Button>
                </div>

                {/* 컬럼 목록 */}
                {expandedTables.has(table.tableName) && (
                  <div className="bg-gray-25 border-t">
                    {table.columns.map((column) => (
                      <div
                        key={column.columnName}
                        className="flex cursor-pointer items-center space-x-2 p-2 pl-6 hover:bg-gray-100"
                        draggable
                        onDragStart={(e) => {
                          console.log("Drag start - column:", column.columnName, "webType:", column.webType);
                          const widgetType = getWidgetTypeFromWebType(column.webType || "text");
                          console.log("Drag start - widgetType:", widgetType);
                          startDrag(
                            {
                              type: "widget",
                              tableName: table.tableName,
                              columnName: column.columnName,
                              widgetType: widgetType as WebType,
                              label: column.columnLabel || column.columnName,
                              size: { width: 150, height: 40 }, // 픽셀 단위로 변경
                            },
                            e,
                          );
                        }}
                      >
                        <div className="flex-shrink-0">
                          {column.webType === "text" && <Type className="h-3 w-3 text-blue-600" />}
                          {column.webType === "email" && <Type className="h-3 w-3 text-blue-600" />}
                          {column.webType === "tel" && <Type className="h-3 w-3 text-blue-600" />}
                          {column.webType === "number" && <Hash className="h-3 w-3 text-green-600" />}
                          {column.webType === "decimal" && <Hash className="h-3 w-3 text-green-600" />}
                          {column.webType === "date" && <Calendar className="h-3 w-3 text-purple-600" />}
                          {column.webType === "datetime" && <Calendar className="h-3 w-3 text-purple-600" />}
                          {column.webType === "select" && <List className="h-3 w-3 text-orange-600" />}
                          {column.webType === "dropdown" && <List className="h-3 w-3 text-orange-600" />}
                          {column.webType === "textarea" && <AlignLeft className="h-3 w-3 text-indigo-600" />}
                          {column.webType === "text_area" && <AlignLeft className="h-3 w-3 text-indigo-600" />}
                          {column.webType === "checkbox" && <CheckSquare className="h-3 w-3 text-blue-600" />}
                          {column.webType === "boolean" && <CheckSquare className="h-3 w-3 text-blue-600" />}
                          {column.webType === "radio" && <Radio className="h-3 w-3 text-blue-600" />}
                          {column.webType === "code" && <Code className="h-3 w-3 text-gray-600" />}
                          {column.webType === "entity" && <Building className="h-3 w-3 text-cyan-600" />}
                          {column.webType === "file" && <File className="h-3 w-3 text-yellow-600" />}
                        </div>
                        <div className="flex-1">
                          <div className="text-sm font-medium">{column.columnLabel || column.columnName}</div>
                          <div className="text-xs text-gray-500">{column.columnName}</div>
                        </div>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            ))}
          </div>

          {/* 페이징 컨트롤 */}
          {totalPages > 1 && (
            <div className="border-t bg-white p-4">
              <div className="flex items-center justify-between">
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => handlePageChange(currentPage - 1)}
                  disabled={currentPage === 1}
                >
                  이전
                </Button>

                <div className="text-sm text-gray-600">
                  {currentPage} / {totalPages}
                </div>

                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => handlePageChange(currentPage + 1)}
                  disabled={currentPage === totalPages}
                >
                  다음
                </Button>
              </div>
            </div>
          )}
        </div>

        {/* 중앙: 캔버스 영역 */}
        <div className="flex-1 bg-white" ref={scrollContainerRef}>
          <div className="h-full w-full overflow-auto p-6">
            <div
              className="min-h-full rounded-lg border-2 border-dashed border-gray-300 bg-gray-50 p-4"
              onDrop={onDrop}
              onDragOver={onDragOver}
              ref={canvasRef}
              onMouseDown={handleMarqueeStart}
              onMouseMove={handleMarqueeMove}
              onMouseUp={handleMarqueeEnd}
              onContextMenu={handleCanvasContextMenu}
            >
              {layout.components.length === 0 ? (
                <div className="flex h-full items-center justify-center">
                  <div className="text-center text-gray-500">
                    <Grid3X3 className="mx-auto mb-4 h-16 w-16 text-gray-300" />
                    <p className="mb-2 text-lg font-medium">빈 캔버스</p>
                    <p className="text-sm">좌측에서 테이블이나 컬럼을 드래그하여 배치하세요</p>
                  </div>
                </div>
              ) : (
                <div className="relative min-h-[600px]">
                  {/* 그리드 가이드 */}
                  <div className="pointer-events-none absolute inset-0">
                    <div className="grid h-full grid-cols-12 gap-1">
                      {Array.from({ length: 12 }).map((_, i) => (
                        <div key={i} className="border-r border-gray-200 last:border-r-0" />
                      ))}
                    </div>
                  </div>

                  {/* 마키 선택 사각형 */}
                  {selectionState.isSelecting && (
                    <div
                      className="pointer-events-none absolute z-50 border border-blue-400 bg-blue-200/20"
                      style={{
                        left: `${Math.min(selectionState.start.x, selectionState.current.x)}px`,
                        top: `${Math.min(selectionState.start.y, selectionState.current.y)}px`,
                        width: `${Math.abs(selectionState.current.x - selectionState.start.x)}px`,
                        height: `${Math.abs(selectionState.current.y - selectionState.start.y)}px`,
                      }}
                    />
                  )}

                  {/* 컴포넌트들 - 실시간 미리보기 */}
                  {layout.components
                    .filter((component) => !component.parentId) // 최상위 컴포넌트만 렌더링
                    .map((component) => {
                      // 그룹 컴포넌트인 경우 자식 컴포넌트들 가져오기
                      const children =
                        component.type === "group"
                          ? layout.components.filter((child) => child.parentId === component.id)
                          : [];

                      return (
                        <RealtimePreview
                          key={component.id}
                          component={component}
                          isSelected={
                            selectedComponent?.id === component.id ||
                            groupState.selectedComponents.includes(component.id)
                          }
                          onClick={(e) => handleComponentClick(component, e)}
                          onDragStart={(e) => startComponentDrag(component, e)}
                          onDragEnd={endDrag}
                          onGroupToggle={(groupId) => {
                            // 그룹 접기/펼치기 토글
                            const groupComp = component as GroupComponent;
                            updateComponentProperty(groupId, "collapsed", !groupComp.collapsed);
                          }}
                        >
                          {children.map((child) => (
                            <RealtimePreview
                              key={child.id}
                              component={child}
                              isSelected={groupState.selectedComponents.includes(child.id)}
                              onClick={(e) => handleComponentClick(child, e)}
                              onDragStart={(e) => startComponentDrag(child, e)}
                              onDragEnd={endDrag}
                            />
                          ))}
                        </RealtimePreview>
                      );
                    })}
                </div>
              )}
            </div>
          </div>
        </div>

        {/* 우측: 컴포넌트 스타일 편집 */}
        <div className="w-80 border-l bg-gray-50">
          <div className="h-full p-4">
            <h3 className="mb-4 text-lg font-medium">컴포넌트 속성</h3>

            {selectedComponent ? (
              <div className="space-y-4">
                <Card>
                  <CardHeader className="pb-3">
                    <CardTitle className="text-sm font-medium">
                      {selectedComponent.type === "container" && "테이블 속성"}
                      {selectedComponent.type === "widget" && "위젯 속성"}
                    </CardTitle>
                  </CardHeader>
                  <CardContent className="space-y-4">
                    {/* 위치 속성 */}
                    <div className="grid grid-cols-2 gap-4">
                      <div className="space-y-2">
                        <Label htmlFor="positionX">X 위치</Label>
                        <Input
                          id="positionX"
                          type="number"
                          min="0"
                          value={liveSelectedPosition.x}
                          onChange={(e) => {
                            const val = (e.target as HTMLInputElement).valueAsNumber;
                            if (Number.isFinite(val)) {
                              updateComponentProperty(selectedComponent.id, "position.x", Math.round(val));
                            }
                          }}
                        />
                      </div>
                      <div className="space-y-2">
                        <Label htmlFor="positionY">Y 위치</Label>
                        <Input
                          id="positionY"
                          type="number"
                          min="0"
                          value={liveSelectedPosition.y}
                          onChange={(e) => {
                            const val = (e.target as HTMLInputElement).valueAsNumber;
                            if (Number.isFinite(val)) {
                              updateComponentProperty(selectedComponent.id, "position.y", Math.round(val));
                            }
                          }}
                        />
                      </div>
                    </div>

                    {/* 크기 속성 */}
                    <div className="grid grid-cols-2 gap-4">
                      <div className="space-y-2">
                        <Label htmlFor="width">너비 (컬럼)</Label>
                        <Input
                          id="width"
                          type="number"
                          min="20"
                          value={selectedComponent.size.width}
                          onChange={(e) => {
                            const val = (e.target as HTMLInputElement).valueAsNumber;
                            if (Number.isFinite(val)) {
                              updateComponentProperty(
                                selectedComponent.id,
                                "size.width",
                                Math.max(20, Math.round(val)),
                              );
                            }
                          }}
                        />
                      </div>
                      <div className="space-y-2">
                        <Label htmlFor="height">높이 (픽셀)</Label>
                        <Input
                          id="height"
                          type="number"
                          min="20"
                          value={selectedComponent.size.height}
                          onChange={(e) => {
                            const val = (e.target as HTMLInputElement).valueAsNumber;
                            if (Number.isFinite(val)) {
                              updateComponentProperty(
                                selectedComponent.id,
                                "size.height",
                                Math.max(20, Math.round(val)),
                              );
                            }
                          }}
                        />
                      </div>
                    </div>

                    {/* 테이블 정보 */}
                    <Separator />
                    <div className="space-y-2">
                      <Label htmlFor="tableName">테이블명</Label>
                      <Input id="tableName" value={selectedComponent.tableName || ""} readOnly className="bg-gray-50" />
                    </div>

                    {/* 위젯 전용 속성 */}
                    {selectedComponent.type === "widget" && (
                      <>
                        <div className="space-y-2">
                          <Label htmlFor="columnName">컬럼명</Label>
                          <Input
                            id="columnName"
                            value={selectedComponent.columnName || ""}
                            readOnly
                            className="bg-gray-50"
                          />
                        </div>
                        <div className="space-y-2">
                          <Label htmlFor="widgetType">위젯 타입</Label>
                          <Input
                            id="widgetType"
                            value={selectedComponent.widgetType || ""}
                            readOnly
                            className="bg-gray-50"
                          />
                        </div>
                        <div className="space-y-2">
                          <Label htmlFor="widgetLabel">라벨</Label>
                          <Input
                            id="widgetLabel"
                            value={selectedComponent.label || ""}
                            onChange={(e) => updateComponentProperty(selectedComponent.id, "label", e.target.value)}
                          />
                        </div>
                        <div className="space-y-2">
                          <Label htmlFor="widgetPlaceholder">플레이스홀더</Label>
                          <Input
                            id="widgetPlaceholder"
                            value={selectedComponent.placeholder || ""}
                            onChange={(e) =>
                              updateComponentProperty(selectedComponent.id, "placeholder", e.target.value)
                            }
                          />
                        </div>
                        <div className="flex items-center space-x-4">
                          <div className="flex items-center space-x-2">
                            <input
                              type="checkbox"
                              id="required"
                              checked={selectedComponent.required || false}
                              onChange={(e) =>
                                updateComponentProperty(selectedComponent.id, "required", e.target.checked)
                              }
                            />
                            <Label htmlFor="required">필수</Label>
                          </div>
                          <div className="flex items-center space-x-2">
                            <input
                              type="checkbox"
                              id="readonly"
                              checked={selectedComponent.readonly || false}
                              onChange={(e) =>
                                updateComponentProperty(selectedComponent.id, "readonly", e.target.checked)
                              }
                            />
                            <Label htmlFor="readonly">읽기 전용</Label>
                          </div>
                        </div>
                      </>
                    )}

                    {/* 스타일 속성 */}
                    <Separator />
                    <div>
                      <Label className="text-sm font-medium">스타일 편집</Label>
                      <StyleEditor
                        style={selectedComponent.style || {}}
                        onStyleChange={(newStyle) => updateComponentProperty(selectedComponent.id, "style", newStyle)}
                      />
                    </div>

                    {/* 고급 속성 */}
                    <Separator />
                    <div className="space-y-2">
                      <Label htmlFor="parentId">부모 ID</Label>
                      <Input id="parentId" value={selectedComponent.parentId || ""} readOnly className="bg-gray-50" />
                    </div>
                    <Button variant="destructive" size="sm" onClick={deleteComponents} className="w-full">
                      <Trash2 className="mr-2 h-4 w-4" />
                      {selectedComponent.type === "group"
                        ? "그룹 삭제"
                        : groupState.selectedComponents.length > 1
                          ? `${groupState.selectedComponents.length}개 삭제`
                          : "컴포넌트 삭제"}
                    </Button>
                  </CardContent>
                </Card>
              </div>
            ) : (
              <div className="py-8 text-center text-gray-500">
                <Settings className="mx-auto mb-2 h-12 w-12 text-gray-300" />
                <p>컴포넌트를 선택하여 속성을 편집하세요</p>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}
