"use client";

import { useRef, useState, useEffect } from "react";
import { ComponentConfig } from "@/types/report";
import { useReportDesigner } from "@/contexts/ReportDesignerContext";
import { MM_TO_PX, DIVIDER_HIT_AREA_PX } from "@/lib/report/constants";
import { evaluateConditionalRules, type ConditionalRule } from "@/lib/report/conditionalUtils";

const HANDLE_SIZE = 8;
const HANDLE_PX = `${HANDLE_SIZE}px`;

type HandleDef = {
  dir: string;
  cursor: string;
  size: string;
  top?: string;
  left?: string;
  right?: string;
  bottom?: string;
  transform: string;
};

const RESIZE_HANDLES_ALL: HandleDef[] = [
  { dir: "nw", cursor: "cursor-nw-resize", size: HANDLE_PX, top: "0", left: "0", transform: "translate(-50%,-50%)" },
  { dir: "n",  cursor: "cursor-n-resize",  size: HANDLE_PX, top: "0", left: "50%", transform: "translate(-50%,-50%)" },
  { dir: "ne", cursor: "cursor-ne-resize", size: HANDLE_PX, top: "0", right: "0", transform: "translate(50%,-50%)" },
  { dir: "w",  cursor: "cursor-w-resize",  size: HANDLE_PX, top: "50%", left: "0", transform: "translate(-50%,-50%)" },
  { dir: "e",  cursor: "cursor-e-resize",  size: HANDLE_PX, top: "50%", right: "0", transform: "translate(50%,-50%)" },
  { dir: "sw", cursor: "cursor-sw-resize", size: HANDLE_PX, bottom: "0", left: "0", transform: "translate(-50%,50%)" },
  { dir: "s",  cursor: "cursor-s-resize",  size: HANDLE_PX, bottom: "0", left: "50%", transform: "translate(-50%,50%)" },
  { dir: "se", cursor: "cursor-se-resize", size: HANDLE_PX, bottom: "0", right: "0", transform: "translate(50%,50%)" },
];

const RESIZE_HANDLES_HORIZONTAL_DIVIDER: HandleDef[] = [
  { dir: "w", cursor: "cursor-w-resize", size: HANDLE_PX, top: "50%", left: "0", transform: "translate(-50%,-50%)" },
  { dir: "e", cursor: "cursor-e-resize", size: HANDLE_PX, top: "50%", right: "0", transform: "translate(50%,-50%)" },
];

const RESIZE_HANDLES_VERTICAL_DIVIDER: HandleDef[] = [
  { dir: "n", cursor: "cursor-n-resize", size: HANDLE_PX, top: "0", left: "50%", transform: "translate(-50%,-50%)" },
  { dir: "s", cursor: "cursor-s-resize", size: HANDLE_PX, bottom: "0", left: "50%", transform: "translate(-50%,50%)" },
];

import {
  TextRenderer,
  TableRenderer,
  ImageRenderer,
  DividerRenderer,
  SignatureRenderer,
  StampRenderer,
  PageNumberRenderer,
  CardRenderer,
  CalculationRenderer,
  BarcodeCanvasRenderer,
  CheckboxRenderer,
} from "./renderers";

interface CanvasComponentProps {
  component: ComponentConfig;
}

export function CanvasComponent({ component }: CanvasComponentProps) {
  const {
    components,
    selectedComponentId,
    selectedComponentIds,
    selectComponent,
    selectMultipleComponents,
    updateComponent,
    getQueryResult,
    snapValueToGrid,
    calculateAlignmentGuides,
    clearAlignmentGuides,
    canvasWidth,
    canvasHeight,
    margins,
    layoutConfig,
    currentPageId,
    duplicateAtPosition,
    openComponentModal,
    removeComponent,
  } = useReportDesigner();
  const [isDragging, setIsDragging] = useState(false);
  const [isResizing, setIsResizing] = useState(false);
  const [resizeDirection, setResizeDirection] = useState("");
  const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
  const [resizeStart, setResizeStart] = useState({ x: 0, y: 0, width: 0, height: 0, compX: 0, compY: 0 });
  const componentRef = useRef<HTMLDivElement>(null);

  // Alt+드래그 복제를 위한 상태
  const [isAltDuplicating, setIsAltDuplicating] = useState(false);
  const duplicatedIdsRef = useRef<string[]>([]);
  // 복제 시 원본 컴포넌트들의 위치 저장 (상대적 위치 유지용)
  const originalPositionsRef = useRef<Map<string, { x: number; y: number }>>(new Map());

  const isSelected = selectedComponentId === component.id;
  const isMultiSelected = selectedComponentIds.includes(component.id);
  const isLocked = component.locked === true;
  const isGrouped = !!component.groupId;

  // 표시할 값 결정
  const getDisplayValue = (): string => {
    if (component.fieldName) {
      // 쿼리가 연결되어 있으면 실제 데이터 조회
      if (component.queryId) {
        const queryResult = getQueryResult(component.queryId);
        if (queryResult && queryResult.rows.length > 0) {
          const firstRow = queryResult.rows[0];
          const value = firstRow[component.fieldName];
          if (value !== null && value !== undefined) {
            return String(value);
          }
        }
      }

      // 기본값이 있으면 기본값 표시, 없으면 필드명 플레이스홀더
      if (component.defaultValue) {
        return component.defaultValue;
      }
      return `{${component.fieldName}}`;
    }

    if (component.defaultValue) {
      return component.defaultValue;
    }

    return "";
  };

  // 텍스트 컴포넌트: 더블 클릭 시 컨텐츠에 맞게 크기 조절
  const fitTextToContent = () => {
    if (isLocked) return;
    if (component.type !== "text" && component.type !== "label") return;

    const minWidth = 50;
    const minHeight = 30;

    // 여백을 px로 변환
    const marginRightPx = margins.right * MM_TO_PX;
    const marginBottomPx = margins.bottom * MM_TO_PX;
    const canvasWidthPx = canvasWidth * MM_TO_PX;
    const canvasHeightPx = canvasHeight * MM_TO_PX;

    // 최대 크기 (여백 고려)
    const maxWidth = canvasWidthPx - marginRightPx - component.x;
    const maxHeight = canvasHeightPx - marginBottomPx - component.y;

    const displayValue = getDisplayValue();
    const fontSize = component.fontSize || 14;

    // 줄바꿈으로 분리하여 각 줄의 너비 측정
    const lines = displayValue.split("\n");
    let maxLineWidth = 0;

    lines.forEach((line) => {
      const measureEl = document.createElement("span");
      measureEl.style.position = "absolute";
      measureEl.style.visibility = "hidden";
      measureEl.style.whiteSpace = "nowrap";
      measureEl.style.fontSize = `${fontSize}px`;
      measureEl.style.fontWeight = component.fontWeight || "normal";
      measureEl.style.fontFamily = component.fontFamily || "Malgun Gothic";
      measureEl.textContent = line || " "; // 빈 줄은 공백으로
      document.body.appendChild(measureEl);

      const lineWidth = measureEl.getBoundingClientRect().width;
      maxLineWidth = Math.max(maxLineWidth, lineWidth);
      document.body.removeChild(measureEl);
    });

    // component.padding 기반 패딩 계산 + 여유분
    const parsePadding = (p: string | number | undefined): number => {
      if (p == null) return 8; // 기본값 8px
      if (typeof p === "number") return p;
      const parts = p.trim().split(/\s+/);
      // "0 8px" → 좌우 8, "8px" → 전체 8
      if (parts.length >= 2) {
        return parseFloat(parts[1]) || 0;
      }
      return parseFloat(parts[0]) || 0;
    };
    const pad = parsePadding(component.padding);
    const horizontalPadding = pad * 2 + 8;
    const verticalPadding = pad * 2 + 4;

    // 줄 높이 계산 (font-size * line-height 약 1.5)
    const lineHeight = fontSize * 1.5;
    const totalHeight = lines.length * lineHeight;

    const finalWidth = Math.min(maxLineWidth + horizontalPadding, maxWidth);
    const finalHeight = Math.min(totalHeight + verticalPadding, maxHeight);

    const newWidth = Math.max(minWidth, finalWidth);
    const newHeight = Math.max(minHeight, finalHeight);

    // 크기 업데이트
    updateComponent(component.id, {
      width: snapValueToGrid(newWidth),
      height: snapValueToGrid(newHeight),
    });
  };

  // 더블 클릭 → 인캔버스 설정 모달 오픈 (Phase 5)
  const handleDoubleClick = (e: React.MouseEvent) => {
    if (isLocked) return;
    if (component.type === "divider") return;
    e.stopPropagation();
    openComponentModal(component.id);
  };

  // 드래그 시작
  const handleMouseDown = (e: React.MouseEvent) => {
    if ((e.target as HTMLElement).classList.contains("resize-handle")) {
      return;
    }

    // 잠긴 컴포넌트는 드래그 불가
    if (isLocked) {
      e.stopPropagation();
      // Ctrl/Cmd 키 감지 (다중 선택)
      const isMultiSelect = e.ctrlKey || e.metaKey;
      selectComponent(component.id, isMultiSelect);
      return;
    }

    e.stopPropagation();

    // Ctrl/Cmd 키 감지 (다중 선택)
    const isMultiSelect = e.ctrlKey || e.metaKey;
    // Alt 키 감지 (복제 드래그)
    const isAltPressed = e.altKey;

    // 이미 다중 선택의 일부인 경우: 선택 상태 유지 (드래그만 시작)
    const isPartOfMultiSelection = selectedComponentIds.length > 1 && selectedComponentIds.includes(component.id);

    if (!isPartOfMultiSelection) {
      // 그룹화된 컴포넌트 클릭 시: 같은 그룹의 모든 컴포넌트 선택
      if (isGrouped && !isMultiSelect) {
        const groupMembers = components.filter((c) => c.groupId === component.groupId);
        const groupMemberIds = groupMembers.map((c) => c.id);
        // 첫 번째 컴포넌트를 선택하고, 나머지를 다중 선택에 추가
        selectComponent(groupMemberIds[0], false);
        groupMemberIds.slice(1).forEach((id) => selectComponent(id, true));
      } else {
        selectComponent(component.id, isMultiSelect);
      }
    }

    // Alt+드래그: 복제 모드
    if (isAltPressed) {
      // 복제할 컴포넌트 ID 목록 결정
      let idsToClone: string[] = [];

      if (isPartOfMultiSelection) {
        // 다중 선택된 경우: 잠기지 않은 선택된 모든 컴포넌트 복제
        idsToClone = selectedComponentIds.filter((id) => {
          const c = components.find((comp) => comp.id === id);
          return c && !c.locked;
        });
      } else if (isGrouped) {
        // 그룹화된 경우: 같은 그룹의 모든 컴포넌트 복제
        idsToClone = components.filter((c) => c.groupId === component.groupId && !c.locked).map((c) => c.id);
      } else {
        // 단일 컴포넌트
        idsToClone = [component.id];
      }

      if (idsToClone.length > 0) {
        // 원본 컴포넌트들의 위치 저장 (복제본 ID -> 원본 위치 매핑용)
        const positionsMap = new Map<string, { x: number; y: number }>();
        idsToClone.forEach((id) => {
          const comp = components.find((c) => c.id === id);
          if (comp) {
            positionsMap.set(id, { x: comp.x, y: comp.y });
          }
        });

        // 복제 생성 (오프셋 없이 원래 위치에)
        const newIds = duplicateAtPosition(idsToClone, 0, 0);
        if (newIds.length > 0) {
          // 복제된 컴포넌트 ID와 원본 위치 매핑
          // newIds[i]는 idsToClone[i]에서 복제됨
          const dupPositionsMap = new Map<string, { x: number; y: number }>();
          newIds.forEach((newId, index) => {
            const originalId = idsToClone[index];
            const originalPos = positionsMap.get(originalId);
            if (originalPos) {
              dupPositionsMap.set(newId, originalPos);
            }
          });
          originalPositionsRef.current = dupPositionsMap;

          // 복제된 컴포넌트들을 선택하고 드래그 시작
          duplicatedIdsRef.current = newIds;
          setIsAltDuplicating(true);

          // 복제된 컴포넌트들 선택
          if (newIds.length === 1) {
            selectComponent(newIds[0], false);
          } else {
            selectMultipleComponents(newIds);
          }
        }
      }
    }

    setIsDragging(true);

    const hitAreaOffsetY = isHorizontalDivider ? (DIVIDER_HIT_AREA - component.height) / 2 : 0;
    const hitAreaOffsetX = isVerticalDivider ? (DIVIDER_HIT_AREA - component.width) / 2 : 0;
    setDragStart({
      x: e.clientX - component.x + hitAreaOffsetX,
      y: e.clientY - component.y + hitAreaOffsetY,
    });
  };

  // 리사이즈 시작 (방향 인자)
  const handleResizeStart = (e: React.MouseEvent, direction: string) => {
    if (isLocked) {
      e.stopPropagation();
      return;
    }

    e.stopPropagation();
    setIsResizing(true);
    setResizeDirection(direction);
    setResizeStart({
      x: e.clientX,
      y: e.clientY,
      width: component.width,
      height: component.height,
      compX: component.x,
      compY: component.y,
    });
  };

  // 마우스 이동 핸들러 (전역)
  useEffect(() => {
    if (!isDragging && !isResizing) return;

    const handleMouseMove = (e: MouseEvent) => {
      if (isDragging) {
        const newX = Math.max(0, e.clientX - dragStart.x);
        const newY = Math.max(0, e.clientY - dragStart.y);

        // 여백을 px로 변환
        const marginTopPx = margins.top * MM_TO_PX;
        const marginBottomPx = margins.bottom * MM_TO_PX;
        const marginLeftPx = margins.left * MM_TO_PX;
        const marginRightPx = margins.right * MM_TO_PX;

        // 캔버스 경계 체크 (mm를 px로 변환)
        const canvasWidthPx = canvasWidth * MM_TO_PX;
        const canvasHeightPx = canvasHeight * MM_TO_PX;

        // 컴포넌트가 여백 안에 있도록 제한
        const minX = marginLeftPx;
        const minY = marginTopPx;
        const maxX = canvasWidthPx - marginRightPx - component.width;
        const maxY = canvasHeightPx - marginBottomPx - component.height;

        const boundedX = Math.min(Math.max(minX, newX), maxX);
        const boundedY = Math.min(Math.max(minY, newY), maxY);

        const snappedX = snapValueToGrid(boundedX);
        const snappedY = snapValueToGrid(boundedY);

        // 정렬 가이드라인 계산
        calculateAlignmentGuides(component.id, snappedX, snappedY, component.width, component.height);

        // 이동 거리 계산
        const deltaX = snappedX - component.x;
        const deltaY = snappedY - component.y;

        // Alt+드래그 복제 모드: 원본은 이동하지 않고 복제본만 이동
        if (isAltDuplicating && duplicatedIdsRef.current.length > 0) {
          // 복제된 컴포넌트들 이동 (각각의 원본 위치 기준으로 절대 위치 설정)
          duplicatedIdsRef.current.forEach((dupId) => {
            const dupComp = components.find((c) => c.id === dupId);
            const originalPos = originalPositionsRef.current.get(dupId);

            if (dupComp && originalPos) {
              // 각 복제본의 원본 위치에서 delta만큼 이동
              const targetX = originalPos.x + deltaX;
              const targetY = originalPos.y + deltaY;

              // 경계 체크
              const dupMaxX = canvasWidthPx - marginRightPx - dupComp.width;
              const dupMaxY = canvasHeightPx - marginBottomPx - dupComp.height;

              updateComponent(dupId, {
                x: Math.min(Math.max(marginLeftPx, targetX), dupMaxX),
                y: Math.min(Math.max(marginTopPx, targetY), dupMaxY),
              });
            }
          });
          return; // 원본 컴포넌트는 이동하지 않음
        }

        // 현재 컴포넌트 이동
        updateComponent(component.id, {
          x: snappedX,
          y: snappedY,
        });

        // 다중 선택된 경우: 선택된 다른 컴포넌트들도 함께 이동
        if (selectedComponentIds.length > 1 && selectedComponentIds.includes(component.id)) {
          components.forEach((c) => {
            // 현재 컴포넌트는 이미 이동됨, 잠긴 컴포넌트는 제외
            if (c.id !== component.id && selectedComponentIds.includes(c.id) && !c.locked) {
              const newMultiX = c.x + deltaX;
              const newMultiY = c.y + deltaY;

              // 경계 체크
              const multiMaxX = canvasWidthPx - marginRightPx - c.width;
              const multiMaxY = canvasHeightPx - marginBottomPx - c.height;

              updateComponent(c.id, {
                x: Math.min(Math.max(marginLeftPx, newMultiX), multiMaxX),
                y: Math.min(Math.max(marginTopPx, newMultiY), multiMaxY),
              });
            }
          });
        }
        // 그룹화된 경우: 같은 그룹의 다른 컴포넌트도 함께 이동
        else if (isGrouped) {
          components.forEach((c) => {
            if (c.groupId === component.groupId && c.id !== component.id) {
              const newGroupX = c.x + deltaX;
              const newGroupY = c.y + deltaY;

              // 그룹 컴포넌트도 경계 체크
              const groupMaxX = canvasWidthPx - c.width;
              const groupMaxY = canvasHeightPx - c.height;

              updateComponent(c.id, {
                x: Math.min(Math.max(0, newGroupX), groupMaxX),
                y: Math.min(Math.max(0, newGroupY), groupMaxY),
              });
            }
          });
        }
      } else if (isResizing) {
        const deltaX = e.clientX - resizeStart.x;
        const deltaY = e.clientY - resizeStart.y;

        const marginTopPx = margins.top * MM_TO_PX;
        const marginLeftPx = margins.left * MM_TO_PX;
        const marginRightPx = margins.right * MM_TO_PX;
        const marginBottomPx = margins.bottom * MM_TO_PX;
        const canvasWidthPx = canvasWidth * MM_TO_PX;
        const canvasHeightPx = canvasHeight * MM_TO_PX;

        const dir = resizeDirection;
        const resizesLeft = dir.includes("w");
        const resizesRight = dir.includes("e");
        const resizesTop = dir.includes("n");
        const resizesBottom = dir.includes("s");

        let newX = resizeStart.compX;
        let newY = resizeStart.compY;
        let newW = resizeStart.width;
        let newH = resizeStart.height;

        if (resizesRight) {
          newW = resizeStart.width + deltaX;
        }
        if (resizesLeft) {
          newW = resizeStart.width - deltaX;
          newX = resizeStart.compX + deltaX;
        }
        if (resizesBottom) {
          newH = resizeStart.height + deltaY;
        }
        if (resizesTop) {
          newH = resizeStart.height - deltaY;
          newY = resizeStart.compY + deltaY;
        }

        const MIN_W = 20;
        const MIN_H = 10;

        // 최소 크기 제한 + 위치 보정
        if (newW < MIN_W) {
          if (resizesLeft) newX = resizeStart.compX + resizeStart.width - MIN_W;
          newW = MIN_W;
        }
        if (newH < MIN_H) {
          if (resizesTop) newY = resizeStart.compY + resizeStart.height - MIN_H;
          newH = MIN_H;
        }

        // 캔버스 경계 제한
        if (newX < marginLeftPx) {
          newW -= marginLeftPx - newX;
          newX = marginLeftPx;
        }
        if (newY < marginTopPx) {
          newH -= marginTopPx - newY;
          newY = marginTopPx;
        }
        const maxRight = canvasWidthPx - marginRightPx;
        const maxBottom = canvasHeightPx - marginBottomPx;
        if (newX + newW > maxRight) newW = maxRight - newX;
        if (newY + newH > maxBottom) newH = maxBottom - newY;

        // 구분선: 방향에 따라 한 축만 조절
        if (component.type === "divider") {
          if (component.orientation === "vertical") {
            updateComponent(component.id, {
              y: snapValueToGrid(newY),
              height: snapValueToGrid(newH),
            });
          } else {
            updateComponent(component.id, {
              x: snapValueToGrid(newX),
              width: snapValueToGrid(newW),
            });
          }
        } else if (component.type === "barcode" && component.barcodeType === "QR") {
          const maxDelta = Math.abs(deltaX) > Math.abs(deltaY) ? deltaX : deltaY;
          const newSize = Math.max(50, resizeStart.width + maxDelta);
          const maxSize = Math.min(maxRight - component.x, maxBottom - component.y);
          const snappedSize = snapValueToGrid(Math.min(newSize, maxSize));
          updateComponent(component.id, { width: snappedSize, height: snappedSize });
        } else {
          updateComponent(component.id, {
            x: snapValueToGrid(newX),
            y: snapValueToGrid(newY),
            width: snapValueToGrid(newW),
            height: snapValueToGrid(newH),
          });
        }
      }
    };

    const handleMouseUp = () => {
      setIsDragging(false);
      setIsResizing(false);
      // Alt 복제 상태 초기화
      setIsAltDuplicating(false);
      duplicatedIdsRef.current = [];
      originalPositionsRef.current = new Map();
      // 가이드라인 초기화
      clearAlignmentGuides();
    };

    document.addEventListener("mousemove", handleMouseMove);
    document.addEventListener("mouseup", handleMouseUp);

    return () => {
      document.removeEventListener("mousemove", handleMouseMove);
      document.removeEventListener("mouseup", handleMouseUp);
    };
  }, [
    isDragging,
    isResizing,
    isAltDuplicating,
    resizeDirection,
    dragStart.x,
    dragStart.y,
    resizeStart.x,
    resizeStart.y,
    resizeStart.width,
    resizeStart.height,
    resizeStart.compX,
    resizeStart.compY,
    component.id,
    component.x,
    component.y,
    component.width,
    component.height,
    component.groupId,
    isGrouped,
    components,
    updateComponent,
    snapValueToGrid,
    calculateAlignmentGuides,
    clearAlignmentGuides,
    canvasWidth,
    canvasHeight,
  ]);

  const isConditionalVisible = (() => {
    const isGrid = component.gridMode === true;
    const rulesArr = isGrid ? component.gridConditionalRules : component.conditionalRules;
    const singleRule = isGrid ? component.gridConditionalRule : component.conditionalRule;
    const rules: ConditionalRule[] = rulesArr?.length
      ? (rulesArr as ConditionalRule[])
      : singleRule
        ? [singleRule as ConditionalRule]
        : [];
    return evaluateConditionalRules(rules, getQueryResult);
  })();

  const isDivider = component.type === "divider";
  const isHorizontalDivider = isDivider && component.orientation !== "vertical";
  const isVerticalDivider = isDivider && component.orientation === "vertical";
  const DIVIDER_HIT_AREA = DIVIDER_HIT_AREA_PX;

  // 컴포넌트 타입별 렌더링
  const renderContent = () => {
    const displayValue = getDisplayValue();

    switch (component.type) {
      case "text":
      case "label":
        return <TextRenderer component={component} getQueryResult={getQueryResult} displayValue={displayValue} />;
      case "table":
        return <TableRenderer component={component} getQueryResult={getQueryResult} />;
      case "image":
        return <ImageRenderer component={component} />;
      case "divider":
        return (
          <div
            className="flex items-center justify-center"
            style={{
              width: `${component.width}px`,
              height: `${component.height}px`,
              position: "absolute",
              top: isHorizontalDivider ? "50%" : 0,
              left: isVerticalDivider ? "50%" : 0,
              transform: `translate(${isVerticalDivider ? "-50%" : "0"}, ${isHorizontalDivider ? "-50%" : "0"})`,
            }}
          >
            <DividerRenderer component={component} />
          </div>
        );
      case "signature":
        return <SignatureRenderer component={component} />;
      case "stamp":
        return <StampRenderer component={component} />;
      case "pageNumber":
        return <PageNumberRenderer component={component} currentPageId={currentPageId} layoutConfig={layoutConfig} />;
      case "card":
        return <CardRenderer component={component} getQueryResult={getQueryResult} />;
      case "calculation":
        return <CalculationRenderer component={component} getQueryResult={getQueryResult} />;
      case "barcode":
        return <BarcodeCanvasRenderer component={component} getQueryResult={getQueryResult} />;
      case "checkbox":
        return <CheckboxRenderer component={component} getQueryResult={getQueryResult} />;
      default:
        return <div>알 수 없는 컴포넌트</div>;
    }
  };

  return (
    <div
      ref={componentRef}
      className={`absolute shadow-sm ${isLocked ? "cursor-not-allowed opacity-80" : "cursor-move"} ${
        isSelected
          ? isLocked
            ? "ring-2 ring-red-500"
            : isGrouped
              ? "ring-2 ring-purple-500"
              : "ring-2 ring-blue-500"
          : isMultiSelected
            ? isLocked
              ? "ring-2 ring-red-300"
              : isGrouped
                ? "ring-2 ring-purple-300"
                : "ring-2 ring-blue-300"
            : ""
      }`}
      style={{
        left: `${component.x}px`,
        top: isHorizontalDivider
          ? `${component.y - (DIVIDER_HIT_AREA - component.height) / 2}px`
          : `${component.y}px`,
        width: isVerticalDivider
          ? `${Math.max(component.width, DIVIDER_HIT_AREA)}px`
          : `${component.width}px`,
        height: isHorizontalDivider
          ? `${Math.max(component.height, DIVIDER_HIT_AREA)}px`
          : `${component.height}px`,
        zIndex: component.zIndex,
        padding: isDivider
          ? 0
          : component.padding != null
            ? typeof component.padding === "number"
              ? `${component.padding}px`
              : component.padding
            : "8px",
        boxSizing: "border-box",
        backgroundColor: isDivider ? "transparent" : component.backgroundColor,
        opacity: isConditionalVisible ? undefined : 0.35,
        border: isDivider
          ? isSelected || isMultiSelected
            ? undefined
            : "none"
          : component.borderWidth
            ? `${component.borderWidth}px solid ${component.borderColor}`
            : "1px solid #e5e7eb",
        borderRadius: component.borderRadius ? `${component.borderRadius}px` : undefined,
      }}
      onMouseDown={handleMouseDown}
      onDoubleClick={handleDoubleClick}
    >
      {renderContent()}

      {/* 조건부 표시 미충족 오버레이 (디자인 모드에서는 숨기지 않고 표시) */}
      {!isConditionalVisible && (
        <div
          className="pointer-events-none absolute inset-0 border-2 border-dashed border-amber-400"
          title="표시 조건: 조건 미충족"
        >
          <div className="absolute top-0 right-0 rounded-bl bg-amber-400 px-1 py-0.5 text-[9px] font-medium text-amber-900">
            조건부
          </div>
        </div>
      )}

      {/* 잠금 표시 (클릭 시 잠금 해제) */}
      {isLocked && (
        <button
          className="absolute top-1 right-1 z-20 rounded bg-red-500 px-1.5 py-0.5 text-[10px] text-white shadow hover:bg-red-600 transition-colors cursor-pointer"
          title="클릭하여 잠금 해제"
          onMouseDown={(e) => e.stopPropagation()}
          onClick={(e) => {
            e.stopPropagation();
            updateComponent(component.id, { locked: false });
          }}
        >
          🔒
        </button>
      )}

      {/* 삭제 버튼 (선택 + 잠금 해제 상태에서만 표시) */}
      {isSelected && !isLocked && (
        <button
          className={`absolute z-20 flex items-center justify-center rounded-full bg-red-500 text-white shadow hover:bg-red-600 transition-colors ${
            isDivider
              ? "h-[18px] w-[18px] -top-5 right-1"
              : "h-5 w-5 -top-2.5 -right-2.5"
          }`}
          title="컴포넌트 삭제"
          onMouseDown={(e) => e.stopPropagation()}
          onClick={(e) => {
            e.stopPropagation();
            removeComponent(component.id);
          }}
        >
          <span className={`font-bold leading-none ${isDivider ? "text-[10px]" : "text-xs"}`}>×</span>
        </button>
      )}

      {/* 그룹화 표시 */}
      {isGrouped && (
        <div className="absolute bottom-1 left-1 flex items-center gap-0.5 rounded bg-purple-500/90 px-1.5 py-0.5 text-[9px] font-medium text-white shadow-sm">
          <svg className="h-2.5 w-2.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
            <rect x="2" y="2" width="8" height="8" rx="1" />
            <rect x="14" y="2" width="8" height="8" rx="1" />
            <rect x="2" y="14" width="8" height="8" rx="1" />
            <rect x="14" y="14" width="8" height="8" rx="1" />
          </svg>
          그룹
        </div>
      )}

      {/* 8방향 리사이즈 핸들 */}
      {isSelected && !isLocked && (
        <>
          {(isDivider
            ? component.orientation === "vertical"
              ? RESIZE_HANDLES_VERTICAL_DIVIDER
              : RESIZE_HANDLES_HORIZONTAL_DIVIDER
            : RESIZE_HANDLES_ALL
          ).map((h) => (
            <div
              key={h.dir}
              className={`resize-handle absolute z-10 ${h.cursor}`}
              style={{
                width: h.size,
                height: h.size,
                top: h.top,
                left: h.left,
                right: h.right,
                bottom: h.bottom,
                transform: h.transform,
                backgroundColor: "#3b82f6",
                borderRadius: "50%",
              }}
              onMouseDown={(e) => handleResizeStart(e, h.dir)}
            />
          ))}
        </>
      )}
    </div>
  );
}
