"use client";

import { useCallback, useRef, useState, useEffect } from "react";
import { useDrop } from "react-dnd";
import { cn } from "@/lib/utils";
import {
  PopLayoutDataV3,
  PopLayoutModeKey,
  PopComponentType,
  GridPosition,
  MODE_RESOLUTIONS,
} from "./types/pop-layout";
import { DND_ITEM_TYPES, DragItemComponent } from "./panels/PopPanel";
import { ZoomIn, ZoomOut, Maximize2 } from "lucide-react";
import { Button } from "@/components/ui/button";

// ========================================
// 타입 정의
// ========================================
type DeviceType = "mobile" | "tablet";

// 모드별 라벨
const MODE_LABELS: Record<PopLayoutModeKey, string> = {
  tablet_landscape: "태블릿 가로",
  tablet_portrait: "태블릿 세로",
  mobile_landscape: "모바일 가로",
  mobile_portrait: "모바일 세로",
};

// 컴포넌트 타입별 라벨
const COMPONENT_TYPE_LABELS: Record<PopComponentType, string> = {
  "pop-field": "필드",
  "pop-button": "버튼",
  "pop-list": "리스트",
  "pop-indicator": "인디케이터",
  "pop-scanner": "스캐너",
  "pop-numpad": "숫자패드",
};

// ========================================
// Props
// ========================================
interface PopCanvasProps {
  layout: PopLayoutDataV3;
  activeDevice: DeviceType;
  activeModeKey: PopLayoutModeKey;
  onModeKeyChange: (modeKey: PopLayoutModeKey) => void;
  selectedComponentId: string | null;
  onSelectComponent: (id: string | null) => void;
  onUpdateComponentPosition: (componentId: string, position: GridPosition, modeKey?: PopLayoutModeKey) => void;
  onDropComponent: (type: PopComponentType, gridPosition: GridPosition) => void;
  onDeleteComponent: (componentId: string) => void;
}

// ========================================
// 메인 컴포넌트
// ========================================
export function PopCanvas({
  layout,
  activeDevice,
  activeModeKey,
  onModeKeyChange,
  selectedComponentId,
  onSelectComponent,
  onUpdateComponentPosition,
  onDropComponent,
  onDeleteComponent,
}: PopCanvasProps) {
  const { settings, components, layouts } = layout;
  const canvasGrid = settings.canvasGrid;

  // 줌 상태 (0.3 ~ 1.5 범위)
  const [canvasScale, setCanvasScale] = useState(0.6);

  // 패닝 상태
  const [isPanning, setIsPanning] = useState(false);
  const [panStart, setPanStart] = useState({ x: 0, y: 0 });
  const [isSpacePressed, setIsSpacePressed] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);

  // 줌 컨트롤
  const handleZoomIn = () => setCanvasScale((prev) => Math.min(1.5, prev + 0.1));
  const handleZoomOut = () => setCanvasScale((prev) => Math.max(0.3, prev - 0.1));
  const handleZoomFit = () => setCanvasScale(1.0);

  // 패닝
  const handlePanStart = (e: React.MouseEvent) => {
    const isMiddleButton = e.button === 1;
    const isScrollAreaClick = (e.target as HTMLElement).classList.contains("canvas-scroll-area");
    if (isMiddleButton || isSpacePressed || isScrollAreaClick) {
      setIsPanning(true);
      setPanStart({ x: e.clientX, y: e.clientY });
      e.preventDefault();
    }
  };

  const handlePanMove = (e: React.MouseEvent) => {
    if (!isPanning || !containerRef.current) return;
    const deltaX = e.clientX - panStart.x;
    const deltaY = e.clientY - panStart.y;
    containerRef.current.scrollLeft -= deltaX;
    containerRef.current.scrollTop -= deltaY;
    setPanStart({ x: e.clientX, y: e.clientY });
  };

  const handlePanEnd = () => setIsPanning(false);

  // 마우스 휠 줌
  const handleWheel = useCallback((e: React.WheelEvent) => {
    e.preventDefault();
    const delta = e.deltaY > 0 ? -0.1 : 0.1;
    setCanvasScale((prev) => Math.max(0.3, Math.min(1.5, prev + delta)));
  }, []);

  // Space 키 감지
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.code === "Space" && !isSpacePressed) setIsSpacePressed(true);
    };
    const handleKeyUp = (e: KeyboardEvent) => {
      if (e.code === "Space") setIsSpacePressed(false);
    };
    window.addEventListener("keydown", handleKeyDown);
    window.addEventListener("keyup", handleKeyUp);
    return () => {
      window.removeEventListener("keydown", handleKeyDown);
      window.removeEventListener("keyup", handleKeyUp);
    };
  }, [isSpacePressed]);

  // 초기 로드 시 캔버스 중앙 스크롤
  useEffect(() => {
    if (containerRef.current) {
      const container = containerRef.current;
      const timer = setTimeout(() => {
        const scrollX = (container.scrollWidth - container.clientWidth) / 2;
        const scrollY = (container.scrollHeight - container.clientHeight) / 2;
        container.scrollTo(scrollX, scrollY);
      }, 100);
      return () => clearTimeout(timer);
    }
  }, [activeDevice]);

  // 현재 디바이스의 가로/세로 모드 키
  const landscapeModeKey: PopLayoutModeKey = activeDevice === "tablet" 
    ? "tablet_landscape" 
    : "mobile_landscape";
  const portraitModeKey: PopLayoutModeKey = activeDevice === "tablet" 
    ? "tablet_portrait" 
    : "mobile_portrait";

  return (
    <div className="relative flex h-full flex-col bg-gray-50">
      {/* 줌 컨트롤 바 */}
      <div className="flex shrink-0 items-center justify-end gap-2 border-b bg-white px-4 py-2">
        <span className="text-xs text-muted-foreground">
          줌: {Math.round(canvasScale * 100)}%
        </span>
        <Button variant="outline" size="icon" className="h-7 w-7" onClick={handleZoomOut} title="줌 아웃">
          <ZoomOut className="h-4 w-4" />
        </Button>
        <Button variant="outline" size="icon" className="h-7 w-7" onClick={handleZoomIn} title="줌 인">
          <ZoomIn className="h-4 w-4" />
        </Button>
        <Button variant="outline" size="icon" className="h-7 w-7" onClick={handleZoomFit} title="맞춤 (100%)">
          <Maximize2 className="h-4 w-4" />
        </Button>
      </div>

      {/* 캔버스 영역 */}
      <div
        ref={containerRef}
        className={cn(
          "relative flex-1 overflow-auto",
          isPanning && "cursor-grabbing",
          isSpacePressed && "cursor-grab"
        )}
        onMouseDown={handlePanStart}
        onMouseMove={handlePanMove}
        onMouseUp={handlePanEnd}
        onMouseLeave={handlePanEnd}
        onWheel={handleWheel}
      >
        <div 
          className="canvas-scroll-area flex items-center justify-center gap-16"
          style={{ padding: "500px", minWidth: "fit-content", minHeight: "fit-content" }}
        >
          {/* 가로 모드 */}
          <DeviceFrame
            modeKey={landscapeModeKey}
            isActive={landscapeModeKey === activeModeKey}
            scale={canvasScale}
            canvasGrid={canvasGrid}
            layout={layout}
            selectedComponentId={selectedComponentId}
            onModeKeyChange={onModeKeyChange}
            onSelectComponent={onSelectComponent}
            onUpdateComponentPosition={onUpdateComponentPosition}
            onDropComponent={onDropComponent}
            onDeleteComponent={onDeleteComponent}
          />
          
          {/* 세로 모드 */}
          <DeviceFrame
            modeKey={portraitModeKey}
            isActive={portraitModeKey === activeModeKey}
            scale={canvasScale}
            canvasGrid={canvasGrid}
            layout={layout}
            selectedComponentId={selectedComponentId}
            onModeKeyChange={onModeKeyChange}
            onSelectComponent={onSelectComponent}
            onUpdateComponentPosition={onUpdateComponentPosition}
            onDropComponent={onDropComponent}
            onDeleteComponent={onDeleteComponent}
          />
        </div>
      </div>
    </div>
  );
}

// ========================================
// CSS Grid 기반 디바이스 프레임 (v3: 컴포넌트 직접 배치)
// ========================================
interface DeviceFrameProps {
  modeKey: PopLayoutModeKey;
  isActive: boolean;
  scale: number;
  canvasGrid: { columns: number; rows: number; gap: number };
  layout: PopLayoutDataV3;
  selectedComponentId: string | null;
  onModeKeyChange: (modeKey: PopLayoutModeKey) => void;
  onSelectComponent: (id: string | null) => void;
  onUpdateComponentPosition: (componentId: string, position: GridPosition, modeKey?: PopLayoutModeKey) => void;
  onDropComponent: (type: PopComponentType, gridPosition: GridPosition) => void;
  onDeleteComponent: (componentId: string) => void;
}

function DeviceFrame({
  modeKey,
  isActive,
  scale,
  canvasGrid,
  layout,
  selectedComponentId,
  onModeKeyChange,
  onSelectComponent,
  onUpdateComponentPosition,
  onDropComponent,
  onDeleteComponent,
}: DeviceFrameProps) {
  const gridRef = useRef<HTMLDivElement>(null);
  const dropRef = useRef<HTMLDivElement>(null);
  
  const { components, layouts } = layout;
  const resolution = MODE_RESOLUTIONS[modeKey];
  const modeLayout = layouts[modeKey];
  const componentPositions = modeLayout.componentPositions;
  const componentIds = Object.keys(componentPositions);

  const cols = canvasGrid.columns;
  const rows = canvasGrid.rows || 24;
  const gap = canvasGrid.gap;

  // 드래그 상태
  const [dragState, setDragState] = useState<{
    componentId: string;
    startPos: GridPosition;
    currentPos: GridPosition;
    isDragging: boolean;
  } | null>(null);

  // 리사이즈 상태
  const [resizeState, setResizeState] = useState<{
    componentId: string;
    startPos: GridPosition;
    currentPos: GridPosition;
    handle: "se" | "sw" | "ne" | "nw" | "e" | "w" | "n" | "s";
    isResizing: boolean;
  } | null>(null);

  // 라벨
  const sizeLabel = `${resolution.width}x${resolution.height}`;
  const modeLabel = `${MODE_LABELS[modeKey]} (${sizeLabel})`;

  // 마우스 → 그리드 좌표 변환
  const getGridPosition = useCallback((clientX: number, clientY: number): { col: number; row: number } => {
    if (!gridRef.current) return { col: 1, row: 1 };
    const rect = gridRef.current.getBoundingClientRect();
    const x = (clientX - rect.left) / scale;
    const y = (clientY - rect.top) / scale;
    const cellWidth = (resolution.width - gap * (cols + 1)) / cols;
    const cellHeight = (resolution.height - gap * (rows + 1)) / rows;
    const col = Math.max(1, Math.min(cols, Math.floor((x - gap) / (cellWidth + gap)) + 1));
    const row = Math.max(1, Math.min(rows, Math.floor((y - gap) / (cellHeight + gap)) + 1));
    return { col, row };
  }, [scale, resolution, cols, rows, gap]);

  // 드래그 시작
  const handleDragStart = useCallback((e: React.MouseEvent, componentId: string) => {
    if (!isActive) return;
    e.preventDefault();
    e.stopPropagation();
    const pos = componentPositions[componentId];
    setDragState({
      componentId,
      startPos: { ...pos },
      currentPos: { ...pos },
      isDragging: true,
    });
  }, [isActive, componentPositions]);

  // 마우스 이동
  const handleMouseMove = useCallback((e: React.MouseEvent) => {
    if (dragState?.isDragging && gridRef.current) {
      const { col, row } = getGridPosition(e.clientX, e.clientY);
      const newCol = Math.max(1, Math.min(cols - dragState.startPos.colSpan + 1, col));
      const newRow = Math.max(1, Math.min(rows - dragState.startPos.rowSpan + 1, row));
      setDragState(prev => prev ? {
        ...prev,
        currentPos: { ...prev.startPos, col: newCol, row: newRow }
      } : null);
    }
    
    if (resizeState?.isResizing && gridRef.current) {
      const { col, row } = getGridPosition(e.clientX, e.clientY);
      const startPos = resizeState.startPos;
      let newPos = { ...startPos };
      
      switch (resizeState.handle) {
        case "se":
          newPos.colSpan = Math.max(2, col - startPos.col + 1);
          newPos.rowSpan = Math.max(2, row - startPos.row + 1);
          break;
        case "e":
          newPos.colSpan = Math.max(2, col - startPos.col + 1);
          break;
        case "s":
          newPos.rowSpan = Math.max(2, row - startPos.row + 1);
          break;
        case "sw":
          const newColSW = Math.min(col, startPos.col + startPos.colSpan - 2);
          newPos.col = newColSW;
          newPos.colSpan = startPos.col + startPos.colSpan - newColSW;
          newPos.rowSpan = Math.max(2, row - startPos.row + 1);
          break;
        case "w":
          const newColW = Math.min(col, startPos.col + startPos.colSpan - 2);
          newPos.col = newColW;
          newPos.colSpan = startPos.col + startPos.colSpan - newColW;
          break;
        case "ne":
          const newRowNE = Math.min(row, startPos.row + startPos.rowSpan - 2);
          newPos.row = newRowNE;
          newPos.rowSpan = startPos.row + startPos.rowSpan - newRowNE;
          newPos.colSpan = Math.max(2, col - startPos.col + 1);
          break;
        case "n":
          const newRowN = Math.min(row, startPos.row + startPos.rowSpan - 2);
          newPos.row = newRowN;
          newPos.rowSpan = startPos.row + startPos.rowSpan - newRowN;
          break;
        case "nw":
          const newColNW = Math.min(col, startPos.col + startPos.colSpan - 2);
          const newRowNW = Math.min(row, startPos.row + startPos.rowSpan - 2);
          newPos.col = newColNW;
          newPos.row = newRowNW;
          newPos.colSpan = startPos.col + startPos.colSpan - newColNW;
          newPos.rowSpan = startPos.row + startPos.rowSpan - newRowNW;
          break;
      }
      
      newPos.col = Math.max(1, newPos.col);
      newPos.row = Math.max(1, newPos.row);
      newPos.colSpan = Math.min(cols - newPos.col + 1, newPos.colSpan);
      newPos.rowSpan = Math.min(rows - newPos.row + 1, newPos.rowSpan);
      
      setResizeState(prev => prev ? { ...prev, currentPos: newPos } : null);
    }
  }, [dragState, resizeState, getGridPosition, cols, rows]);

  // 드래그/리사이즈 종료
  const handleMouseUp = useCallback(() => {
    if (dragState?.isDragging) {
      onUpdateComponentPosition(dragState.componentId, dragState.currentPos, modeKey);
      setDragState(null);
    }
    if (resizeState?.isResizing) {
      onUpdateComponentPosition(resizeState.componentId, resizeState.currentPos, modeKey);
      setResizeState(null);
    }
  }, [dragState, resizeState, onUpdateComponentPosition, modeKey]);

  // 리사이즈 시작
  const handleResizeStart = useCallback((e: React.MouseEvent, componentId: string, handle: string) => {
    if (!isActive) return;
    e.preventDefault();
    e.stopPropagation();
    const pos = componentPositions[componentId];
    setResizeState({
      componentId,
      startPos: { ...pos },
      currentPos: { ...pos },
      handle: handle as any,
      isResizing: true,
    });
  }, [isActive, componentPositions]);

  // 컴포넌트 드롭
  const [{ isOver, canDrop }, drop] = useDrop(
    () => ({
      accept: DND_ITEM_TYPES.COMPONENT,
      drop: (item: DragItemComponent, monitor) => {
        if (!isActive) return;
        const clientOffset = monitor.getClientOffset();
        if (!clientOffset || !gridRef.current) return;
        const { col, row } = getGridPosition(clientOffset.x, clientOffset.y);
        onDropComponent(item.componentType, { col, row, colSpan: 4, rowSpan: 3 });
      },
      canDrop: () => isActive,
      collect: (monitor) => ({
        isOver: monitor.isOver(),
        canDrop: monitor.canDrop(),
      }),
    }),
    [isActive, getGridPosition, onDropComponent]
  );

  drop(dropRef);

  // 현재 표시할 위치
  const getDisplayPosition = (componentId: string): GridPosition => {
    if (dragState?.componentId === componentId && dragState.isDragging) {
      return dragState.currentPos;
    }
    if (resizeState?.componentId === componentId && resizeState.isResizing) {
      return resizeState.currentPos;
    }
    return componentPositions[componentId];
  };

  return (
    <div className="relative shrink-0">
      {/* 모드 라벨 */}
      <div
        className={cn(
          "absolute -top-6 left-1/2 -translate-x-1/2 whitespace-nowrap text-xs font-medium",
          isActive ? "text-primary" : "text-muted-foreground"
        )}
      >
        {modeLabel}
      </div>

      {/* 디바이스 프레임 */}
      <div
        ref={dropRef}
        className={cn(
          "relative cursor-pointer overflow-hidden rounded-xl bg-white shadow-lg transition-all",
          isActive ? "ring-2 ring-primary ring-offset-2" : "ring-1 ring-gray-200 hover:ring-gray-300",
          isOver && canDrop && "ring-2 ring-primary bg-primary/5"
        )}
        style={{
          width: resolution.width * scale,
          height: resolution.height * scale,
        }}
        onClick={(e) => {
          if (e.target === e.currentTarget) {
            if (!isActive) onModeKeyChange(modeKey);
            else onSelectComponent(null);
          }
        }}
        onMouseMove={handleMouseMove}
        onMouseUp={handleMouseUp}
        onMouseLeave={handleMouseUp}
      >
        {/* CSS Grid (뷰어와 동일) */}
        <div
          ref={gridRef}
          className="origin-top-left"
          style={{
            transform: `scale(${scale})`,
            width: resolution.width,
            height: resolution.height,
            display: "grid",
            gridTemplateColumns: `repeat(${cols}, 1fr)`,
            gridTemplateRows: `repeat(${rows}, 1fr)`,
            gap: `${gap}px`,
            padding: `${gap}px`,
          }}
        >
          {componentIds.length > 0 ? (
            componentIds.map((componentId) => {
              const compDef = components[componentId];
              if (!compDef) return null;

              const pos = getDisplayPosition(componentId);
              const isSelected = selectedComponentId === componentId;
              const isDragging = dragState?.componentId === componentId && dragState.isDragging;
              const isResizing = resizeState?.componentId === componentId && resizeState.isResizing;

              return (
                <div
                  key={componentId}
                  className={cn(
                    "group relative flex cursor-move items-center justify-center overflow-hidden rounded-lg border-2 bg-white transition-all",
                    isSelected
                      ? "border-primary ring-2 ring-primary/30"
                      : "border-gray-200 hover:border-gray-300",
                    (isDragging || isResizing) && "opacity-80 shadow-xl z-50"
                  )}
                  style={{
                    gridColumn: `${pos.col} / span ${pos.colSpan}`,
                    gridRow: `${pos.row} / span ${pos.rowSpan}`,
                  }}
                  onClick={(e) => {
                    e.stopPropagation();
                    if (!isActive) onModeKeyChange(modeKey);
                    onSelectComponent(componentId);
                  }}
                  onMouseDown={(e) => handleDragStart(e, componentId)}
                >
                  {/* 컴포넌트 라벨 */}
                  <span className="text-xs text-gray-500 select-none">
                    {compDef.label || COMPONENT_TYPE_LABELS[compDef.type]}
                  </span>

                  {/* 리사이즈 핸들 */}
                  {isActive && isSelected && (
                    <>
                      <div className="absolute -right-1 -bottom-1 h-3 w-3 cursor-se-resize rounded-full bg-primary" onMouseDown={(e) => handleResizeStart(e, componentId, "se")} />
                      <div className="absolute -left-1 -bottom-1 h-3 w-3 cursor-sw-resize rounded-full bg-primary" onMouseDown={(e) => handleResizeStart(e, componentId, "sw")} />
                      <div className="absolute -right-1 -top-1 h-3 w-3 cursor-ne-resize rounded-full bg-primary" onMouseDown={(e) => handleResizeStart(e, componentId, "ne")} />
                      <div className="absolute -left-1 -top-1 h-3 w-3 cursor-nw-resize rounded-full bg-primary" onMouseDown={(e) => handleResizeStart(e, componentId, "nw")} />
                      <div className="absolute right-0 top-1/2 h-6 w-1.5 -translate-y-1/2 cursor-e-resize rounded bg-primary/50" onMouseDown={(e) => handleResizeStart(e, componentId, "e")} />
                      <div className="absolute left-0 top-1/2 h-6 w-1.5 -translate-y-1/2 cursor-w-resize rounded bg-primary/50" onMouseDown={(e) => handleResizeStart(e, componentId, "w")} />
                      <div className="absolute bottom-0 left-1/2 h-1.5 w-6 -translate-x-1/2 cursor-s-resize rounded bg-primary/50" onMouseDown={(e) => handleResizeStart(e, componentId, "s")} />
                      <div className="absolute top-0 left-1/2 h-1.5 w-6 -translate-x-1/2 cursor-n-resize rounded bg-primary/50" onMouseDown={(e) => handleResizeStart(e, componentId, "n")} />
                    </>
                  )}
                </div>
              );
            })
          ) : (
            <div
              className={cn(
                "col-span-full row-span-full flex items-center justify-center text-sm",
                isOver && canDrop ? "text-primary" : "text-gray-400"
              )}
            >
              {isOver && canDrop
                ? "여기에 컴포넌트를 놓으세요"
                : isActive
                ? "왼쪽 패널에서 컴포넌트를 드래그하세요"
                : "클릭하여 편집"}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
