"use client";

import { useState, useCallback, useEffect, useMemo, useRef } from "react";
import { Group, Database, Trash2, Copy, Clipboard } from "lucide-react";
import {
  ScreenDefinition,
  ComponentData,
  LayoutData,
  GroupState,
  WebType,
  TableInfo,
  GroupComponent,
  Position,
} from "@/types/screen";
import { generateComponentId } from "@/lib/utils/generateId";
import {
  createGroupComponent,
  calculateBoundingBox,
  calculateRelativePositions,
  restoreAbsolutePositions,
  getGroupChildren,
} from "@/lib/utils/groupingUtils";
import {
  calculateGridInfo,
  snapToGrid,
  snapSizeToGrid,
  generateGridLines,
  GridSettings as GridUtilSettings,
} from "@/lib/utils/gridUtils";
import { GroupingToolbar } from "./GroupingToolbar";
import { screenApi } from "@/lib/api/screen";
import { toast } from "sonner";

import StyleEditor from "./StyleEditor";
import { RealtimePreview } from "./RealtimePreview";
import FloatingPanel from "./FloatingPanel";
import DesignerToolbar from "./DesignerToolbar";
import TablesPanel from "./panels/TablesPanel";
import PropertiesPanel from "./panels/PropertiesPanel";
import GridPanel from "./panels/GridPanel";
import { usePanelState, PanelConfig } from "@/hooks/usePanelState";

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

// 패널 설정
const panelConfigs: PanelConfig[] = [
  {
    id: "tables",
    title: "테이블 목록",
    defaultPosition: "left",
    defaultWidth: 320,
    defaultHeight: 600,
    shortcutKey: "t",
  },
  {
    id: "properties",
    title: "속성 편집",
    defaultPosition: "right",
    defaultWidth: 320,
    defaultHeight: 500,
    shortcutKey: "p",
  },
  {
    id: "styles",
    title: "스타일 편집",
    defaultPosition: "right",
    defaultWidth: 320,
    defaultHeight: 400,
    shortcutKey: "s",
  },
  {
    id: "grid",
    title: "격자 설정",
    defaultPosition: "right",
    defaultWidth: 280,
    defaultHeight: 450,
    shortcutKey: "g",
  },
];

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

  const [layout, setLayout] = useState<LayoutData>({
    components: [],
    gridSettings: { columns: 12, gap: 16, padding: 16, snapToGrid: true, showGrid: true },
  });
  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[]>([]);
  const [historyIndex, setHistoryIndex] = useState(-1);

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

  // 드래그 상태
  const [dragState, setDragState] = useState({
    isDragging: false,
    draggedComponent: null as ComponentData | null,
    originalPosition: { x: 0, y: 0 },
    currentPosition: { x: 0, y: 0 },
    grabOffset: { x: 0, y: 0 },
  });

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

  // 클립보드
  const [clipboard, setClipboard] = useState<{
    type: "single" | "multiple" | "group";
    data: ComponentData[];
  } | null>(null);

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

  const canvasRef = useRef<HTMLDivElement>(null);

  // 격자 정보 계산
  const gridInfo = useMemo(() => {
    if (!canvasRef.current || !layout.gridSettings) return null;
    return calculateGridInfo(canvasRef.current, layout.gridSettings);
  }, [layout.gridSettings]);

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

  // 필터된 테이블 목록
  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));
      setHasUnsavedChanges(true);
    },
    [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) => {
      const pathParts = path.split(".");
      const updatedComponents = layout.components.map((comp) => {
        if (comp.id !== componentId) 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;

        // 크기 변경 시 격자 스냅 적용
        if ((path === "size.width" || path === "size.height") && layout.gridSettings?.snapToGrid && gridInfo) {
          const snappedSize = snapSizeToGrid(newComp.size, gridInfo, layout.gridSettings as GridUtilSettings);
          newComp.size = snappedSize;
        }

        return newComp;
      });

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

  // 테이블 데이터 로드
  useEffect(() => {
    if (selectedScreen?.tableName) {
      const loadTables = async () => {
        try {
          setIsLoading(true);
          const response = await screenApi.getTableInfo([selectedScreen.tableName]);
          setTables(response.data || []);
        } catch (error) {
          // console.error("테이블 정보 로드 실패:", error);
          toast.error("테이블 정보를 불러오는데 실패했습니다.");
        } finally {
          setIsLoading(false);
        }
      };
      loadTables();
    }
  }, [selectedScreen?.tableName]);

  // 화면 레이아웃 로드
  useEffect(() => {
    if (selectedScreen?.screenId) {
      const loadLayout = async () => {
        try {
          setIsLoading(true);
          const response = await screenApi.getScreenLayout(selectedScreen.screenId);
          if (response.success && response.data) {
            setLayout(response.data);
            setHistory([response.data]);
            setHistoryIndex(0);
            setHasUnsavedChanges(false);
          }
        } catch (error) {
          // console.error("레이아웃 로드 실패:", error);
          toast.error("화면 레이아웃을 불러오는데 실패했습니다.");
        } finally {
          setIsLoading(false);
        }
      };
      loadLayout();
    }
  }, [selectedScreen?.screenId]);

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

    try {
      setIsSaving(true);
      
      // 🔍 디버깅: 저장할 레이아웃 데이터 확인
      console.log("🔍 레이아웃 저장 요청:", {
        screenId: selectedScreen.screenId,
        componentsCount: layout.components.length,
        components: layout.components.map(c => ({
          id: c.id,
          type: c.type,
          webTypeConfig: (c as any).webTypeConfig,
        })),
      });
      
      const response = await screenApi.saveScreenLayout(selectedScreen.screenId, layout);
      if (response.success) {
        toast.success("화면이 저장되었습니다.");
        setHasUnsavedChanges(false);
      } else {
        toast.error("저장에 실패했습니다.");
      }
    } catch (error) {
      // console.error("저장 실패:", error);
      toast.error("저장 중 오류가 발생했습니다.");
    } finally {
      setIsSaving(false);
    }
  }, [selectedScreen?.screenId, layout]);

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

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

      const dragData = e.dataTransfer.getData("application/json");
      if (!dragData) return;

      try {
        const { type, table, column } = JSON.parse(dragData);
        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 },
            size: { width: 300, height: 200 },
          };
        } else if (type === "column") {
          // 컬럼 위젯 생성
          newComponent = {
            id: generateComponentId(),
            type: "widget",
            label: column.columnLabel || column.columnName, // 컬럼 라벨 우선, 없으면 컬럼명
            tableName: table.tableName,
            columnName: column.columnName,
            widgetType: column.widgetType,
            dataType: column.dataType,
            required: column.required,
            position: { x, y, z: 1 },
            size: { width: 200, height: 40 },
          };
        } else {
          return;
        }

        // 격자 스냅 적용
        if (layout.gridSettings?.snapToGrid && gridInfo) {
          newComponent.position = snapToGrid(newComponent.position, gridInfo, layout.gridSettings as GridUtilSettings);
          newComponent.size = snapSizeToGrid(newComponent.size, gridInfo, layout.gridSettings as GridUtilSettings);
        }

        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();
      setSelectedComponent(component);

      // 속성 패널 자동 열기
      openPanel("properties");
    },
    [openPanel],
  );

  // 컴포넌트 삭제
  const deleteComponent = useCallback(() => {
    if (!selectedComponent) return;

    const newComponents = layout.components.filter((comp) => comp.id !== selectedComponent.id);
    const newLayout = { ...layout, components: newComponents };

    setLayout(newLayout);
    saveToHistory(newLayout);
    setSelectedComponent(null);
  }, [selectedComponent, layout, saveToHistory]);

  // 컴포넌트 복사
  const copyComponent = useCallback(() => {
    if (!selectedComponent) return;

    setClipboard({
      type: "single",
      data: [{ ...selectedComponent, id: generateComponentId() }],
    });

    toast.success("컴포넌트가 복사되었습니다.");
  }, [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,
          ...relativeChildren,
        ],
      };

      setLayout(newLayout);
      saveToHistory(newLayout);
      setGroupState((prev) => ({ ...prev, selectedComponents: [] }));
    },
    [layout, saveToHistory],
  );

  // 키보드 이벤트 처리
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      // Delete 키로 컴포넌트 삭제
      if (e.key === "Delete" && selectedComponent) {
        deleteComponent();
      }

      // Ctrl+C로 복사
      if (e.ctrlKey && e.key === "c" && selectedComponent) {
        copyComponent();
      }

      // Ctrl+Z로 실행취소
      if (e.ctrlKey && e.key === "z" && !e.shiftKey) {
        e.preventDefault();
        undo();
      }

      // Ctrl+Y 또는 Ctrl+Shift+Z로 다시실행
      if ((e.ctrlKey && e.key === "y") || (e.ctrlKey && e.shiftKey && e.key === "z")) {
        e.preventDefault();
        redo();
      }
    };

    document.addEventListener("keydown", handleKeyDown);
    return () => document.removeEventListener("keydown", handleKeyDown);
  }, [selectedComponent, deleteComponent, copyComponent, undo, redo]);

  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
        ref={canvasRef}
        className="relative flex-1 overflow-hidden bg-white"
        onClick={(e) => {
          if (e.target === e.currentTarget) {
            setSelectedComponent(null);
            setGroupState((prev) => ({ ...prev, selectedComponents: [] }));
          }
        }}
        onDrop={handleDrop}
        onDragOver={handleDragOver}
      >
        {/* 격자 라인 */}
        {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 || "#e5e7eb",
              opacity: layout.gridSettings?.gridOpacity || 0.3,
            }}
          />
        ))}

        {/* 컴포넌트들 */}
        {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}
                onClick={(e) => handleComponentClick(component, e)}
              >
                {children.map((child) => (
                  <RealtimePreview
                    key={child.id}
                    component={child}
                    isSelected={selectedComponent?.id === child.id}
                    onClick={(e) => handleComponentClick(child, e)}
                  />
                ))}
              </RealtimePreview>
            );
          })}

        {/* 빈 캔버스 안내 */}
        {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(테이블), P(속성), S(스타일), G(격자)</p>
            </div>
          </div>
        )}
      </div>

      {/* 플로팅 패널들 */}
      <FloatingPanel
        id="tables"
        title="테이블 목록"
        isOpen={panelStates.tables?.isOpen || false}
        onClose={() => closePanel("tables")}
        position="left"
        width={320}
        height={600}
      >
        <TablesPanel
          tables={filteredTables}
          searchTerm={searchTerm}
          onSearchChange={setSearchTerm}
          onDragStart={(e, table, column) => {
            const dragData = {
              type: column ? "column" : "table",
              table,
              column,
            };
            e.dataTransfer.setData("application/json", JSON.stringify(dragData));
          }}
          selectedTableName={selectedScreen.tableName}
        />
      </FloatingPanel>

      <FloatingPanel
        id="properties"
        title="속성 편집"
        isOpen={panelStates.properties?.isOpen || false}
        onClose={() => closePanel("properties")}
        position="right"
        width={320}
        height={500}
      >
        <PropertiesPanel
          selectedComponent={selectedComponent}
          onUpdateProperty={updateComponentProperty}
          onDeleteComponent={deleteComponent}
          onCopyComponent={copyComponent}
        />
      </FloatingPanel>

      <FloatingPanel
        id="styles"
        title="스타일 편집"
        isOpen={panelStates.styles?.isOpen || false}
        onClose={() => closePanel("styles")}
        position="right"
        width={320}
        height={400}
      >
        {selectedComponent ? (
          <div className="p-4">
            <StyleEditor
              style={selectedComponent.style || {}}
              onStyleChange={(newStyle) => updateComponentProperty(selectedComponent.id, "style", newStyle)}
            />
          </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={280}
        height={450}
      >
        <GridPanel
          gridSettings={layout.gridSettings || { columns: 12, gap: 16, padding: 16, snapToGrid: true, showGrid: true }}
          onGridSettingsChange={(settings) => {
            const newLayout = { ...layout, gridSettings: settings };
            setLayout(newLayout);
            saveToHistory(newLayout);
          }}
          onResetGrid={() => {
            const defaultSettings = { columns: 12, gap: 16, padding: 16, snapToGrid: true, showGrid: true };
            const newLayout = { ...layout, gridSettings: defaultSettings };
            setLayout(newLayout);
            saveToHistory(newLayout);
          }}
        />
      </FloatingPanel>

      {/* 그룹 생성 툴바 (필요시) */}
      {groupState.selectedComponents.length > 1 && (
        <div className="fixed bottom-4 left-1/2 z-50 -translate-x-1/2 transform">
          <GroupingToolbar
            selectedComponents={groupState.selectedComponents}
            onGroupCreate={handleGroupCreate}
            showCreateDialog={showGroupCreateDialog}
            onShowCreateDialogChange={setShowGroupCreateDialog}
          />
        </div>
      )}
    </div>
  );
}
