"use client";

import React, { useState, useEffect, useRef } from "react";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Separator } from "@/components/ui/separator";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
import { ChevronDown } from "lucide-react";
import { Settings, Move, Type, Trash2, Copy, Group, Ungroup } from "lucide-react";
import {
  ComponentData,
  WebType,
  WidgetComponent,
  GroupComponent,
  DataTableComponent,
  AreaComponent,
  AreaLayoutType,
  TableInfo,
} from "@/types/screen";
import { ColumnSpanPreset, COLUMN_SPAN_PRESETS, COLUMN_SPAN_VALUES } from "@/lib/constants/columnSpans";
import { cn } from "@/lib/utils";
import DataTableConfigPanel from "./DataTableConfigPanel";
import { useWebTypes } from "@/hooks/admin/useWebTypes";
import {
  BaseInputType,
  BASE_INPUT_TYPE_OPTIONS,
  getBaseInputType,
  getDefaultDetailType,
} from "@/types/input-type-mapping";

// DataTableConfigPanel을 위한 안정화된 래퍼 컴포넌트
const DataTableConfigPanelWrapper: React.FC<{
  selectedComponent: DataTableComponent;
  tables: TableInfo[];
  activeTab: string;
  onTabChange: (tab: string) => void;
  onUpdateProperty: (property: string, value: any) => void;
}> = React.memo(
  ({ selectedComponent, tables, activeTab, onTabChange, onUpdateProperty }) => {
    // 안정화된 업데이트 핸들러
    const handleUpdateComponent = React.useCallback(
      (updates: Partial<DataTableComponent>) => {
        // console.log("🔄 DataTable 래퍼 컴포넌트 업데이트:", updates);

        // 변경사항이 있는지 확인 (간단한 비교로 성능 향상)
        const hasChanges = Object.entries(updates).some(([key, value]) => {
          const currentValue = (selectedComponent as any)[key];
          // 배열의 경우 길이만 비교
          if (Array.isArray(currentValue) && Array.isArray(value)) {
            return currentValue.length !== value.length;
          }
          // 기본값 비교
          return currentValue !== value;
        });

        if (!hasChanges) {
          // console.log("⏭️ 래퍼: 변경사항 없음, 업데이트 스킵");
          return;
        }

        // 각 속성을 개별적으로 업데이트
        Object.entries(updates).forEach(([key, value]) => {
          onUpdateProperty(key, value);
        });
      },
      [selectedComponent.id, onUpdateProperty],
    ); // ID만 의존성으로 사용

    return (
      <DataTableConfigPanel
        component={selectedComponent}
        tables={tables}
        activeTab={activeTab}
        onTabChange={onTabChange}
        onUpdateComponent={handleUpdateComponent}
      />
    );
  },
  (prevProps, nextProps) => {
    // 컴포넌트 ID가 다르면 리렌더링
    if (prevProps.selectedComponent.id !== nextProps.selectedComponent.id) {
      return false;
    }

    // 테이블 목록이 변경되면 리렌더링
    if (prevProps.tables.length !== nextProps.tables.length) {
      return false;
    }

    // 활성 탭이 변경되면 리렌더링
    if (prevProps.activeTab !== nextProps.activeTab) {
      return false;
    }

    // 그 외의 경우는 리렌더링하지 않음
    return true;
  },
);

interface PropertiesPanelProps {
  selectedComponent?: ComponentData;
  tables?: TableInfo[];
  dragState?: {
    isDragging: boolean;
    draggedComponent: ComponentData | null;
    currentPosition: { x: number; y: number; z: number };
  };
  onUpdateProperty: (path: string, value: unknown) => void;
  onDeleteComponent: () => void;
  onCopyComponent: () => void;
  onGroupComponents?: () => void;
  onUngroupComponents?: () => void;
  canGroup?: boolean;
  canUngroup?: boolean;
}

// 동적 웹타입 옵션은 컴포넌트 내부에서 useWebTypes 훅으로 가져옵니다

const PropertiesPanelComponent: React.FC<PropertiesPanelProps> = ({
  selectedComponent,
  tables = [],
  dragState,
  onUpdateProperty,
  onDeleteComponent,
  onCopyComponent,
  onGroupComponents,
  onUngroupComponents,
  canGroup = false,
  canUngroup = false,
}) => {
  // 🔍 디버깅: PropertiesPanel 렌더링 및 dragState 전달 확인
  // console.log("📍 PropertiesPanel 렌더링:", {
  // renderTime: Date.now(),
  // selectedComponentId: selectedComponent?.id,
  // dragState: dragState
  // ? {
  // isDragging: dragState.isDragging,
  // draggedComponentId: dragState.draggedComponent?.id,
  // currentPosition: dragState.currentPosition,
  // dragStateRef: dragState, // 객체 참조 확인
  // }
  // : "null",
  // });

  // 동적 웹타입 목록 가져오기 - API에서 직접 조회
  const { webTypes, isLoading: isWebTypesLoading } = useWebTypes({ active: "Y" });

  // 강제 리렌더링을 위한 state (드래그 중 실시간 업데이트용)
  const [forceRender, setForceRender] = useState(0);

  // 드래그 상태를 직접 추적하여 리렌더링 강제
  const [lastDragPosition, setLastDragPosition] = useState({ x: 0, y: 0 });

  // 웹타입 옵션 생성 - 데이터베이스 기반
  const webTypeOptions = webTypes.map((webType) => ({
    value: webType.web_type as WebType,
    label: webType.type_name,
  }));

  // 데이터테이블 설정 탭 상태를 여기서 관리
  const [dataTableActiveTab, setDataTableActiveTab] = useState("basic");
  // 최신 값들의 참조를 유지
  const selectedComponentRef = useRef(selectedComponent);
  const onUpdatePropertyRef = useRef(onUpdateProperty);

  // 실시간 위치 계산 (드래그 중일 때는 dragState.currentPosition 사용)
  const getCurrentPosition = () => {
    if (dragState?.isDragging && dragState.draggedComponent?.id === selectedComponent?.id) {
      // console.log("🎯 드래그 중 실시간 위치:", {
      // draggedId: dragState.draggedComponent?.id,
      // selectedId: selectedComponent?.id,
      // currentPosition: dragState.currentPosition,
      // });
      return {
        x: Math.round(dragState.currentPosition.x),
        y: Math.round(dragState.currentPosition.y),
      };
    }
    return {
      x: selectedComponent?.position?.x || 0,
      y: selectedComponent?.position?.y || 0,
    };
  };

  const currentPosition = getCurrentPosition();

  // 입력 필드들의 로컬 상태 (실시간 타이핑 반영용)
  const [localInputs, setLocalInputs] = useState({
    placeholder: (selectedComponent?.type === "widget" ? (selectedComponent as WidgetComponent).placeholder : "") || "",
    title:
      (selectedComponent?.type === "group"
        ? (selectedComponent as GroupComponent).title
        : selectedComponent?.type === "area"
          ? (selectedComponent as AreaComponent).title
          : "") || "",
    description: (selectedComponent?.type === "area" ? (selectedComponent as AreaComponent).description : "") || "",
    positionX: currentPosition.x.toString(),
    positionY: currentPosition.y.toString(),
    positionZ: selectedComponent?.position.z?.toString() || "1",
    width: selectedComponent?.size?.width?.toString() || "0",
    height: selectedComponent?.size?.height?.toString() || "0",
    labelText: selectedComponent?.style?.labelText || selectedComponent?.label || "",
    labelFontSize: selectedComponent?.style?.labelFontSize || "12px",
    labelColor: selectedComponent?.style?.labelColor || "#212121",
    labelMarginBottom: selectedComponent?.style?.labelMarginBottom || "4px",
    required: (selectedComponent?.type === "widget" ? (selectedComponent as WidgetComponent).required : false) || false,
    readonly: (selectedComponent?.type === "widget" ? (selectedComponent as WidgetComponent).readonly : false) || false,
    labelDisplay: selectedComponent?.style?.labelDisplay ?? true,
    // widgetType도 로컬 상태로 관리
    widgetType:
      (selectedComponent?.type === "widget" ? (selectedComponent as WidgetComponent).widgetType : "text") || "text",
  });

  // 너비 드롭다운 로컬 상태 - 실시간 업데이트를 위한 별도 관리
  const calculateWidthSpan = (width: string | number | undefined, gridColumns?: number): string => {
    // gridColumns 값이 있으면 우선 사용
    if (gridColumns) {
      const columnsToSpan: Record<number, string> = {
        1: "twelfth", // 1/12
        2: "small", // 2/12
        3: "quarter", // 3/12
        4: "third", // 4/12
        5: "five-twelfths", // 5/12
        6: "half", // 6/12
        7: "seven-twelfths", // 7/12
        8: "twoThirds", // 8/12
        9: "threeQuarters", // 9/12
        10: "five-sixths", // 10/12
        11: "eleven-twelfths", // 11/12
        12: "full", // 12/12
      };

      const span = columnsToSpan[gridColumns];
      if (span) {
        console.log("🎯 calculateWidthSpan - gridColumns 사용:", { gridColumns, span });
        return span;
      }
    }

    // gridColumns가 없으면 style.width에서 계산
    if (!width) return "half";

    if (typeof width === "string" && width.includes("%")) {
      const percent = parseFloat(width);

      // 정확한 매핑을 위해 가장 가까운 값 찾기
      // 중복 제거: small(작게) 사용, third(1/3) 사용, twoThirds(2/3) 사용, quarter(1/4) 사용, threeQuarters(3/4) 사용
      const percentToSpan: Record<number, string> = {
        100: "full", // 12/12
        91.666667: "eleven-twelfths", // 11/12
        83.333333: "five-sixths", // 10/12
        75: "threeQuarters", // 9/12
        66.666667: "twoThirds", // 8/12
        58.333333: "seven-twelfths", // 7/12
        50: "half", // 6/12
        41.666667: "five-twelfths", // 5/12
        33.333333: "third", // 4/12
        25: "quarter", // 3/12
        16.666667: "small", // 2/12
        8.333333: "twelfth", // 1/12
      };

      // 가장 가까운 퍼센트 값 찾기 (오차 범위 ±2% 허용)
      let closestSpan = "half";
      let minDiff = Infinity;

      for (const [key, span] of Object.entries(percentToSpan)) {
        const diff = Math.abs(percent - parseFloat(key));
        if (diff < minDiff && diff < 5) {
          // 5% 오차 범위 내
          minDiff = diff;
          closestSpan = span;
        }
      }

      console.log("🎯 calculateWidthSpan - width% 사용:", { width, percent, closestSpan });
      return closestSpan;
    }

    return "half";
  };

  const [localWidthSpan, setLocalWidthSpan] = useState<string>(() =>
    calculateWidthSpan(selectedComponent?.style?.width, (selectedComponent as any)?.gridColumns),
  );

  // 컴포넌트 또는 style.width, gridColumns가 변경될 때 로컬 상태 업데이트
  useEffect(() => {
    const newSpan = calculateWidthSpan(selectedComponent?.style?.width, (selectedComponent as any)?.gridColumns);
    setLocalWidthSpan(newSpan);
    console.log("🔄 localWidthSpan 업데이트:", {
      gridColumns: (selectedComponent as any)?.gridColumns,
      width: selectedComponent?.style?.width,
      newSpan,
    });
  }, [selectedComponent?.id, selectedComponent?.style?.width, (selectedComponent as any)?.gridColumns]);

  useEffect(() => {
    selectedComponentRef.current = selectedComponent;
    onUpdatePropertyRef.current = onUpdateProperty;
  });

  // 선택된 컴포넌트가 변경될 때 로컬 입력 상태 업데이트
  useEffect(() => {
    if (selectedComponent) {
      const widget = selectedComponent.type === "widget" ? (selectedComponent as WidgetComponent) : null;
      const group = selectedComponent.type === "group" ? (selectedComponent as GroupComponent) : null;
      const area = selectedComponent.type === "area" ? (selectedComponent as AreaComponent) : null;

      // console.log("🔄 PropertiesPanel: 컴포넌트 변경 감지", {
      // componentId: selectedComponent.id,
      // componentType: selectedComponent.type,
      // isDragging: dragState?.isDragging,
      // justFinishedDrag: dragState?.justFinishedDrag,
      // currentValues: {
      // placeholder: widget?.placeholder,
      // title: group?.title || area?.title,
      // description: area?.description,
      // actualPositionX: selectedComponent.position.x,
      // actualPositionY: selectedComponent.position.y,
      // dragPositionX: dragState?.currentPosition.x,
      // dragPositionY: dragState?.currentPosition.y,
      // },
      // getCurrentPosResult: getCurrentPosition(),
      // });

      // 드래그 중이 아닐 때만 localInputs 업데이트 (드래그 완료 후 최종 위치 반영)
      if (!dragState?.isDragging || dragState.draggedComponent?.id !== selectedComponent.id) {
        const currentPos = getCurrentPosition();
        setLocalInputs({
          placeholder: widget?.placeholder || "",
          title: group?.title || area?.title || "",
          description: area?.description || "",
          positionX: currentPos.x.toString(),
          positionY: currentPos.y.toString(),
          positionZ: selectedComponent?.position?.z?.toString() || "1",
          width: selectedComponent?.size?.width?.toString() || "0", // 안전한 접근
          height: selectedComponent?.size?.height?.toString() || "0", // 안전한 접근
          gridColumns:
            selectedComponent?.gridColumns?.toString() ||
            (selectedComponent?.type === "layout" && (selectedComponent as any)?.layoutType === "card-layout"
              ? "8"
              : "1"),
          labelText: selectedComponent?.style?.labelText || selectedComponent?.label || "",
          labelFontSize: selectedComponent?.style?.labelFontSize || "12px",
          labelColor: selectedComponent?.style?.labelColor || "#212121",
          labelMarginBottom: selectedComponent?.style?.labelMarginBottom || "4px",
          required: widget?.required || false,
          readonly: widget?.readonly || false,
          labelDisplay: selectedComponent.style?.labelDisplay ?? true,
          // widgetType 동기화
          widgetType: widget?.widgetType || "text",
        });

        // console.log("✅ localInputs 업데이트 완료:", {
        // positionX: currentPos.x.toString(),
        // positionY: currentPos.y.toString(),
        // });
      }
    }
  }, [
    selectedComponent?.id, // ID만 감지하여 컴포넌트 변경 시에만 업데이트
    selectedComponent?.position.x, // 컴포넌트 실제 위치 변경 감지 (드래그 완료 후)
    selectedComponent?.position.y,
    selectedComponent?.position.z, // z 위치도 감지
    dragState?.isDragging, // 드래그 상태 변경 감지 (드래그 완료 감지용)
    dragState?.justFinishedDrag, // 드래그 완료 직후 감지
  ]);

  // 🔴 삭제 액션일 때 라벨 색상 자동 설정
  useEffect(() => {
    if (selectedComponent && selectedComponent.type === "component") {
      // 삭제 액션 감지 로직 (실제 필드명 사용)
      const isDeleteAction = () => {
        const deleteKeywords = ["삭제", "delete", "remove", "제거", "del"];
        return (
          selectedComponent.componentConfig?.action?.type === "delete" ||
          selectedComponent.config?.action?.type === "delete" ||
          selectedComponent.webTypeConfig?.actionType === "delete" ||
          selectedComponent.text?.toLowerCase().includes("삭제") ||
          selectedComponent.text?.toLowerCase().includes("delete") ||
          selectedComponent.label?.toLowerCase().includes("삭제") ||
          selectedComponent.label?.toLowerCase().includes("delete") ||
          deleteKeywords.some(
            (keyword) =>
              selectedComponent.config?.buttonText?.toLowerCase().includes(keyword) ||
              selectedComponent.config?.text?.toLowerCase().includes(keyword),
          )
        );
      };

      // 🔍 디버깅: 컴포넌트 구조 확인
      // console.log("🔍 PropertiesPanel 삭제 액션 디버깅:", {
      // componentType: selectedComponent.type,
      // componentId: selectedComponent.id,
      // componentConfig: selectedComponent.componentConfig,
      // config: selectedComponent.config,
      // webTypeConfig: selectedComponent.webTypeConfig,
      // actionType1: selectedComponent.componentConfig?.action?.type,
      // actionType2: selectedComponent.config?.action?.type,
      // actionType3: selectedComponent.webTypeConfig?.actionType,
      // isDeleteAction: isDeleteAction(),
      // currentLabelColor: selectedComponent.style?.labelColor,
      // });

      // 액션에 따른 라벨 색상 자동 설정
      if (isDeleteAction()) {
        // 삭제 액션일 때 빨간색으로 설정 (이미 빨간색이 아닌 경우에만)
        if (selectedComponent.style?.labelColor !== "#ef4444") {
          // console.log("🔴 삭제 액션 감지: 라벨 색상을 빨간색으로 자동 설정");
          onUpdateProperty("style", {
            ...selectedComponent.style,
            labelColor: "#ef4444",
          });

          // 로컬 입력 상태도 업데이트
          setLocalInputs((prev) => ({
            ...prev,
            labelColor: "#ef4444",
          }));
        }
      } else {
        // 다른 액션일 때 기본 파란색으로 리셋 (현재 빨간색인 경우에만)
        if (selectedComponent.style?.labelColor === "#ef4444") {
          // console.log("🔵 일반 액션 감지: 라벨 색상을 기본 파란색으로 리셋");
          onUpdateProperty("style", {
            ...selectedComponent.style,
            labelColor: "#212121",
          });

          // 로컬 입력 상태도 업데이트
          setLocalInputs((prev) => ({
            ...prev,
            labelColor: "#212121",
          }));
        }
      }
    }
  }, [
    selectedComponent?.componentConfig?.action?.type,
    selectedComponent?.config?.action?.type,
    selectedComponent?.webTypeConfig?.actionType,
    selectedComponent?.id,
    selectedComponent?.style?.labelColor, // 라벨 색상 변경도 감지
    JSON.stringify(selectedComponent?.componentConfig), // 전체 componentConfig 변경 감지
    onUpdateProperty,
  ]);

  // 렌더링 시마다 실행되는 직접적인 드래그 상태 체크
  if (dragState?.isDragging && dragState.draggedComponent?.id === selectedComponent?.id) {
    // console.log("🎯 렌더링 중 드래그 상태 감지:", {
    // isDragging: dragState.isDragging,
    // draggedId: dragState.draggedComponent?.id,
    // selectedId: selectedComponent?.id,
    // currentPosition: dragState.currentPosition,
    // });

    const newPosition = {
      x: dragState.currentPosition.x,
      y: dragState.currentPosition.y,
    };

    // 위치가 변경되었는지 확인
    if (lastDragPosition.x !== newPosition.x || lastDragPosition.y !== newPosition.y) {
      // console.log("🔄 위치 변경 감지됨:", {
      // oldPosition: lastDragPosition,
      // newPosition: newPosition,
      // });
      // 다음 렌더링 사이클에서 업데이트
      setTimeout(() => {
        setLastDragPosition(newPosition);
        setForceRender((prev) => prev + 1);
      }, 0);
    }
  }

  if (!selectedComponent) {
    return (
      <div className="flex h-full flex-col items-center justify-center p-6 text-center">
        <Settings className="mb-4 h-12 w-12 text-gray-400" />
        <h3 className="mb-2 text-lg font-medium text-gray-900">컴포넌트를 선택하세요</h3>
        <p className="text-sm text-gray-500">캔버스에서 컴포넌트를 클릭하면 속성을 편집할 수 있습니다.</p>
      </div>
    );
  }

  // 데이터 테이블 컴포넌트인 경우 전용 패널 사용
  if (selectedComponent.type === "datatable") {
    return (
      <div className="flex h-full flex-col">
        {/* 헤더 */}
        <div className="border-b border-gray-200 p-4">
          <div className="mb-3 flex items-center justify-between">
            <div className="flex items-center space-x-2">
              <Settings className="text-muted-foreground h-5 w-5" />
              <span className="text-lg font-semibold">데이터 테이블 설정</span>
            </div>
            <Badge variant="secondary" className="text-xs">
              {selectedComponent.type}
            </Badge>
          </div>

          {/* 액션 버튼들 */}
          <div className="flex flex-wrap gap-2">
            <Button variant="outline" size="sm" onClick={onCopyComponent}>
              <Copy className="mr-1 h-4 w-4" />
              복사
            </Button>
            <Button variant="destructive" size="sm" onClick={onDeleteComponent}>
              <Trash2 className="mr-1 h-4 w-4" />
              삭제
            </Button>
          </div>
        </div>

        {/* 데이터 테이블 설정 패널 */}
        <div className="flex-1 overflow-y-auto">
          <DataTableConfigPanelWrapper
            selectedComponent={selectedComponent as DataTableComponent}
            tables={tables}
            activeTab={dataTableActiveTab}
            onTabChange={setDataTableActiveTab}
            onUpdateProperty={onUpdateProperty}
          />
        </div>
      </div>
    );
  }

  return (
    <div className="flex h-full flex-col">
      {/* 헤더 */}
      <div className="border-b border-gray-200 p-4">
        <div className="mb-3 flex items-center justify-between">
          <div className="flex items-center space-x-2">
            <Settings className="text-muted-foreground h-4 w-4" />
            <h3 className="font-medium text-gray-900">속성 편집</h3>
          </div>
          <Badge variant="secondary" className="text-xs">
            {selectedComponent.type}
          </Badge>
        </div>

        {/* 액션 버튼들 */}
        <div className="flex flex-wrap gap-2">
          <Button size="sm" variant="outline" onClick={onCopyComponent} className="flex items-center space-x-1">
            <Copy className="h-3 w-3" />
            <span>복사</span>
          </Button>

          {canGroup && (
            <Button size="sm" variant="outline" onClick={onGroupComponents} className="flex items-center space-x-1">
              <Group className="h-3 w-3" />
              <span>그룹</span>
            </Button>
          )}

          {canUngroup && (
            <Button size="sm" variant="outline" onClick={onUngroupComponents} className="flex items-center space-x-1">
              <Ungroup className="h-3 w-3" />
              <span>해제</span>
            </Button>
          )}

          <Button size="sm" variant="destructive" onClick={onDeleteComponent} className="flex items-center space-x-1">
            <Trash2 className="h-3 w-3" />
            <span>삭제</span>
          </Button>
        </div>
      </div>

      {/* 속성 편집 영역 */}
      <div className="flex-1 space-y-6 overflow-y-auto p-4">
        {/* 기본 정보 */}
        <div className="space-y-3">
          <div className="flex items-center space-x-2">
            <Type className="text-muted-foreground h-4 w-4" />
            <h4 className="font-medium text-gray-900">기본 정보</h4>
          </div>

          <div className="space-y-3">
            {selectedComponent.type === "widget" && (
              <>
                <div>
                  <Label htmlFor="columnName" className="text-sm font-medium">
                    컬럼명 (읽기 전용)
                  </Label>
                  <Input
                    id="columnName"
                    value={selectedComponent.columnName || ""}
                    readOnly
                    placeholder="데이터베이스 컬럼명"
                    className="text-muted-foreground mt-1 bg-gray-50"
                    title="컬럼명은 변경할 수 없습니다"
                  />
                </div>

                <div>
                  <Label htmlFor="inputType" className="text-sm font-medium">
                    입력 타입
                  </Label>
                  <select
                    className="focus:border-primary mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:ring-1 focus:ring-blue-500 focus:outline-none"
                    value={getBaseInputType(localInputs.widgetType)}
                    onChange={(e) => {
                      const selectedInputType = e.target.value as BaseInputType;
                      // 입력 타입에 맞는 기본 세부 타입 설정
                      const defaultWebType = getDefaultDetailType(selectedInputType);
                      setLocalInputs((prev) => ({ ...prev, widgetType: defaultWebType }));
                      onUpdateProperty("widgetType", defaultWebType);
                    }}
                  >
                    {BASE_INPUT_TYPE_OPTIONS.map((option) => (
                      <option key={option.value} value={option.value}>
                        {option.label} - {option.description}
                      </option>
                    ))}
                  </select>
                  <p className="mt-1 text-xs text-gray-500">세부 타입은 "상세 설정" 패널에서 선택하세요</p>
                </div>

                <div>
                  <Label htmlFor="placeholder" className="text-sm font-medium">
                    플레이스홀더
                  </Label>
                  <Input
                    id="placeholder"
                    value={localInputs.placeholder}
                    onChange={(e) => {
                      const newValue = e.target.value;
                      // console.log("🔄 placeholder 변경:", newValue);
                      setLocalInputs((prev) => ({ ...prev, placeholder: newValue }));
                      onUpdateProperty("placeholder", newValue);
                    }}
                    placeholder="입력 힌트 텍스트"
                    className="mt-1"
                  />
                </div>

                <div className="flex items-center space-x-4">
                  <div className="flex items-center space-x-2">
                    <input
                      type="checkbox"
                      id="required"
                      checked={localInputs.required}
                      onChange={(e) => {
                        setLocalInputs((prev) => ({ ...prev, required: e.target.checked }));
                        onUpdateProperty("required", e.target.checked);
                      }}
                      className="border-input bg-background text-primary focus:ring-ring h-4 w-4 rounded border focus:ring-2 focus:ring-offset-2"
                    />
                    <Label htmlFor="required" className="text-sm">
                      필수 입력
                    </Label>
                  </div>

                  <div className="flex items-center space-x-2">
                    <input
                      type="checkbox"
                      id="readonly"
                      checked={localInputs.readonly}
                      onChange={(e) => {
                        setLocalInputs((prev) => ({ ...prev, readonly: e.target.checked }));
                        onUpdateProperty("readonly", e.target.checked);
                      }}
                      className="border-input bg-background text-primary focus:ring-ring h-4 w-4 rounded border focus:ring-2 focus:ring-offset-2"
                    />
                    <Label htmlFor="readonly" className="text-sm">
                      읽기 전용
                    </Label>
                  </div>
                </div>
              </>
            )}
          </div>
        </div>

        <Separator />

        {/* 위치 및 크기 */}
        <div className="space-y-3">
          <div className="flex items-center space-x-2">
            <Move className="text-muted-foreground h-4 w-4" />
            <h4 className="font-medium text-gray-900">위치 및 크기</h4>
          </div>

          <div className="grid grid-cols-2 gap-3">
            <div>
              <Label htmlFor="positionX" className="text-sm font-medium">
                X 위치
              </Label>
              <Input
                id="positionX"
                type="number"
                value={(() => {
                  const isDragging = dragState?.isDragging && dragState.draggedComponent?.id === selectedComponent?.id;
                  if (isDragging) {
                    const realTimeX = Math.round(dragState.currentPosition.x);
                    // console.log("🔥 실시간 X 렌더링:", realTimeX, "forceRender:", forceRender);
                    return realTimeX.toString();
                  }
                  return localInputs.positionX;
                })()}
                onChange={(e) => {
                  const newValue = e.target.value;
                  setLocalInputs((prev) => ({ ...prev, positionX: newValue }));
                  onUpdateProperty("position.x", Number(newValue));
                }}
                className={`mt-1 ${
                  dragState?.isDragging && dragState.draggedComponent?.id === selectedComponent?.id
                    ? "bg-accent border-blue-300 text-blue-700"
                    : ""
                }`}
                readOnly={dragState?.isDragging && dragState.draggedComponent?.id === selectedComponent?.id}
              />
            </div>

            <div>
              <Label htmlFor="positionY" className="text-sm font-medium">
                Y 위치
              </Label>
              <Input
                id="positionY"
                type="number"
                value={(() => {
                  const isDragging = dragState?.isDragging && dragState.draggedComponent?.id === selectedComponent?.id;
                  if (isDragging) {
                    const realTimeY = Math.round(dragState.currentPosition.y);
                    // console.log("🔥 실시간 Y 렌더링:", realTimeY, "forceRender:", forceRender);
                    return realTimeY.toString();
                  }
                  return localInputs.positionY;
                })()}
                onChange={(e) => {
                  const newValue = e.target.value;
                  setLocalInputs((prev) => ({ ...prev, positionY: newValue }));
                  onUpdateProperty("position.y", Number(newValue));
                }}
                className={`mt-1 ${
                  dragState?.isDragging && dragState.draggedComponent?.id === selectedComponent?.id
                    ? "bg-accent border-blue-300 text-blue-700"
                    : ""
                }`}
                readOnly={dragState?.isDragging && dragState.draggedComponent?.id === selectedComponent?.id}
              />
            </div>

            {/* 카드 레이아웃은 자동 크기 계산으로 너비/높이 설정 숨김 */}
            {selectedComponent?.type !== "layout" || (selectedComponent as any)?.layoutType !== "card" ? (
              <>
                {/* 🆕 컬럼 스팬 선택 (width를 퍼센트로 변환) - 기존 UI 유지 */}
                <div className="col-span-2">
                  <Label className="text-sm font-medium">컴포넌트 너비</Label>
                  <Select
                    value={localWidthSpan}
                    onValueChange={(value) => {
                      // 컬럼 스팬을 퍼센트로 변환
                      const percentages: Record<string, string> = {
                        // 표준 옵션 (드롭다운에 표시됨)
                        twelfth: "8.333333%", // 1/12
                        small: "16.666667%", // 2/12 (작게)
                        quarter: "25%", // 3/12 (1/4)
                        third: "33.333333%", // 4/12 (1/3)
                        "five-twelfths": "41.666667%", // 5/12
                        half: "50%", // 6/12 (절반)
                        "seven-twelfths": "58.333333%", // 7/12
                        twoThirds: "66.666667%", // 8/12 (2/3)
                        threeQuarters: "75%", // 9/12 (3/4)
                        "five-sixths": "83.333333%", // 10/12
                        "eleven-twelfths": "91.666667%", // 11/12
                        full: "100%", // 12/12 (전체)

                        // 레거시 호환성 (드롭다운에는 없지만 기존 데이터 지원)
                        sixth: "16.666667%", // 2/12 (= small)
                        label: "25%", // 3/12 (= quarter)
                        medium: "33.333333%", // 4/12 (= third)
                        large: "66.666667%", // 8/12 (= twoThirds)
                        input: "75%", // 9/12 (= threeQuarters)
                        "two-thirds": "66.666667%", // 케밥케이스 호환
                        "three-quarters": "75%", // 케밥케이스 호환
                      };

                      const newWidth = percentages[value] || "50%";

                      // 로컬 상태 즉시 업데이트
                      setLocalWidthSpan(value);

                      // 컴포넌트 속성 업데이트
                      onUpdateProperty("style.width", newWidth);

                      // gridColumns도 자동 계산하여 업데이트 (1/12 = 1컬럼, 2/12 = 2컬럼, ...)
                      const columnsMap: Record<string, number> = {
                        twelfth: 1,
                        small: 2,
                        quarter: 3,
                        third: 4,
                        "five-twelfths": 5,
                        half: 6,
                        "seven-twelfths": 7,
                        twoThirds: 8,
                        threeQuarters: 9,
                        "five-sixths": 10,
                        "eleven-twelfths": 11,
                        full: 12,
                        // 레거시 호환
                        sixth: 2,
                        label: 3,
                        medium: 4,
                        large: 8,
                        input: 9,
                        "two-thirds": 8,
                        "three-quarters": 9,
                        fiveTwelfths: 5,
                        sevenTwelfths: 7,
                        fiveSixths: 10,
                        elevenTwelfths: 11,
                      };
                      const gridColumns = columnsMap[value] || 6;
                      onUpdateProperty("gridColumns", gridColumns);
                    }}
                  >
                    <SelectTrigger className="mt-1">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      {Object.entries(COLUMN_SPAN_PRESETS)
                        .filter(([key]) => {
                          // auto 제거 및 중복 퍼센트 옵션 제거
                          // 제거할 옵션: auto, label(=quarter), input(=threeQuarters), medium(=third), large(=twoThirds)
                          const excludeKeys = ["auto", "label", "input", "medium", "large"];
                          return !excludeKeys.includes(key);
                        })
                        .map(([key, info]) => (
                          <SelectItem key={key} value={key}>
                            <div className="flex w-full items-center justify-between gap-4">
                              <span>{info.label}</span>
                              <span className="text-xs text-gray-500">
                                {info.value}/12 ({info.percentage})
                              </span>
                            </div>
                          </SelectItem>
                        ))}
                    </SelectContent>
                  </Select>

                  {/* 시각적 프리뷰 - 기존 UI 유지, localWidthSpan 기반 */}
                  <div className="mt-3 space-y-2">
                    <Label className="text-xs text-gray-500">미리보기</Label>
                    <div className="grid h-6 grid-cols-12 gap-0.5 overflow-hidden rounded border">
                      {Array.from({ length: 12 }).map((_, i) => {
                        // localWidthSpan으로부터 활성 컬럼 계산
                        const spanValues: Record<string, number> = {
                          // 표준 옵션
                          twelfth: 1,
                          small: 2,
                          quarter: 3,
                          third: 4,
                          "five-twelfths": 5,
                          half: 6,
                          "seven-twelfths": 7,
                          twoThirds: 8,
                          threeQuarters: 9,
                          "five-sixths": 10,
                          "eleven-twelfths": 11,
                          full: 12,

                          // 레거시 호환성
                          sixth: 2,
                          label: 3,
                          medium: 4,
                          large: 8,
                          input: 9,
                          "two-thirds": 8,
                          "three-quarters": 9,
                        };

                        const spanValue = spanValues[localWidthSpan] || 6;
                        const isActive = i < spanValue;

                        return (
                          <div
                            key={i}
                            className={cn("h-full transition-colors", isActive ? "bg-blue-500" : "bg-gray-100")}
                          />
                        );
                      })}
                    </div>
                    <p className="text-center text-xs text-gray-500">
                      {(() => {
                        const spanValues: Record<string, number> = {
                          // 표준 옵션
                          twelfth: 1,
                          small: 2,
                          quarter: 3,
                          third: 4,
                          "five-twelfths": 5,
                          half: 6,
                          "seven-twelfths": 7,
                          twoThirds: 8,
                          threeQuarters: 9,
                          "five-sixths": 10,
                          "eleven-twelfths": 11,
                          full: 12,

                          // 레거시 호환성
                          sixth: 2,
                          label: 3,
                          medium: 4,
                          large: 8,
                          input: 9,
                          "two-thirds": 8,
                          "three-quarters": 9,
                        };
                        const cols = spanValues[localWidthSpan] || 6;
                        return `${cols} / 12 컬럼`;
                      })()}
                    </p>
                  </div>
                </div>

                <div className="col-span-2">
                  <Label htmlFor="height" className="text-sm font-medium">
                    높이 (40px 단위)
                  </Label>
                  <div className="mt-1 flex items-center space-x-2">
                    <Input
                      id="height"
                      type="number"
                      min="1"
                      max="20"
                      value={Math.round((localInputs.height || 40) / 40)}
                      onChange={(e) => {
                        const rows = Math.max(1, Math.min(20, Number(e.target.value)));
                        const newHeight = rows * 40;
                        setLocalInputs((prev) => ({ ...prev, height: newHeight.toString() }));
                        onUpdateProperty("size.height", newHeight);
                      }}
                      className="flex-1"
                    />
                    <span className="text-sm text-gray-500">행 = {localInputs.height || 40}px</span>
                  </div>
                  <p className="mt-1 text-xs text-gray-500">
                    1행 = 40px (현재 {Math.round((localInputs.height || 40) / 40)}행)
                  </p>
                </div>
              </>
            ) : (
              <div className="bg-accent col-span-2 rounded-lg p-3 text-center">
                <p className="text-primary text-sm">카드 레이아웃은 자동으로 크기가 계산됩니다</p>
                <p className="mt-1 text-xs text-blue-500">카드 개수와 간격 설정은 상세설정에서 조정하세요</p>
              </div>
            )}

            <div>
              <Label htmlFor="zIndex" className="text-sm font-medium">
                Z-Index (레이어 순서)
              </Label>
              <Input
                id="zIndex"
                type="number"
                min="0"
                max="9999"
                value={localInputs.positionZ}
                onChange={(e) => {
                  const newValue = e.target.value;
                  setLocalInputs((prev) => ({ ...prev, positionZ: newValue }));
                  onUpdateProperty("position.z", Number(newValue));
                }}
                className="mt-1"
                placeholder="1"
              />
            </div>
          </div>
        </div>

        <Separator />

        {/* 라벨 스타일 */}
        <div className="space-y-3">
          <div className="flex items-center space-x-2">
            <Type className="text-muted-foreground h-4 w-4" />
            <h4 className="font-medium text-gray-900">라벨 설정</h4>
          </div>

          {/* 라벨 표시 토글 */}
          <div className="flex items-center justify-between">
            <Label htmlFor="labelDisplay" className="text-sm font-medium">
              라벨 표시
            </Label>
            <input
              type="checkbox"
              id="labelDisplay"
              checked={localInputs.labelDisplay}
              onChange={(e) => {
                // console.log("🔄 라벨 표시 변경:", e.target.checked);
                setLocalInputs((prev) => ({ ...prev, labelDisplay: e.target.checked }));
                onUpdateProperty("style.labelDisplay", e.target.checked);
              }}
              className="border-input bg-background text-primary focus:ring-ring h-4 w-4 rounded border focus:ring-2 focus:ring-offset-2"
            />
          </div>

          {/* 라벨 텍스트 */}
          <div>
            <Label htmlFor="labelText" className="text-sm font-medium">
              라벨 텍스트
            </Label>
            <Input
              id="labelText"
              value={localInputs.labelText}
              onChange={(e) => {
                const newValue = e.target.value;
                // console.log("🔄 라벨 텍스트 변경:", newValue);
                setLocalInputs((prev) => ({ ...prev, labelText: newValue }));
                // 기본 라벨과 스타일 라벨을 모두 업데이트
                onUpdateProperty("label", newValue);
                onUpdateProperty("style.labelText", newValue);
              }}
              placeholder="라벨 텍스트"
              className="mt-1"
            />
          </div>

          {/* 라벨 스타일 */}
          <div className="grid grid-cols-2 gap-3">
            <div>
              <Label htmlFor="labelFontSize" className="text-sm font-medium">
                폰트 크기
              </Label>
              <Input
                id="labelFontSize"
                value={localInputs.labelFontSize}
                onChange={(e) => {
                  const newValue = e.target.value;
                  setLocalInputs((prev) => ({ ...prev, labelFontSize: newValue }));
                  onUpdateProperty("style.labelFontSize", newValue);
                }}
                placeholder="12px"
                className="mt-1"
              />
            </div>

            <div>
              <Label htmlFor="labelColor" className="text-sm font-medium">
                색상
              </Label>
              <Input
                id="labelColor"
                type="color"
                value={localInputs.labelColor}
                onChange={(e) => {
                  const newValue = e.target.value;
                  setLocalInputs((prev) => ({ ...prev, labelColor: newValue }));
                  onUpdateProperty("style.labelColor", newValue);
                }}
                className="mt-1 h-8"
              />
            </div>

            <div>
              <Label htmlFor="labelFontWeight" className="text-sm font-medium">
                폰트 굵기
              </Label>
              <select
                className="focus:border-primary mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:ring-1 focus:ring-blue-500 focus:outline-none"
                value={selectedComponent.style?.labelFontWeight || "500"}
                onChange={(e) => onUpdateProperty("style.labelFontWeight", e.target.value)}
              >
                <option value="normal">Normal</option>
                <option value="bold">Bold</option>
                <option value="100">100</option>
                <option value="200">200</option>
                <option value="300">300</option>
                <option value="400">400</option>
                <option value="500">500</option>
                <option value="600">600</option>
                <option value="700">700</option>
                <option value="800">800</option>
                <option value="900">900</option>
              </select>
            </div>

            <div>
              <Label htmlFor="labelTextAlign" className="text-sm font-medium">
                텍스트 정렬
              </Label>
              <select
                className="focus:border-primary mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:ring-1 focus:ring-blue-500 focus:outline-none"
                value={selectedComponent.style?.labelTextAlign || "left"}
                onChange={(e) => onUpdateProperty("style.labelTextAlign", e.target.value)}
              >
                <option value="left">왼쪽</option>
                <option value="center">가운데</option>
                <option value="right">오른쪽</option>
              </select>
            </div>
          </div>

          {/* 라벨 여백 */}
          <div>
            <Label htmlFor="labelMarginBottom" className="text-sm font-medium">
              라벨 하단 여백
            </Label>
            <Input
              id="labelMarginBottom"
              value={localInputs.labelMarginBottom}
              onChange={(e) => {
                const newValue = e.target.value;
                setLocalInputs((prev) => ({ ...prev, labelMarginBottom: newValue }));
                onUpdateProperty("style.labelMarginBottom", newValue);
              }}
              placeholder="4px"
              className="mt-1"
            />
          </div>
        </div>

        {selectedComponent.type === "group" && (
          <>
            <Separator />

            {/* 그룹 설정 */}
            <div className="space-y-3">
              <div className="flex items-center space-x-2">
                <Group className="text-muted-foreground h-4 w-4" />
                <h4 className="font-medium text-gray-900">그룹 설정</h4>
              </div>

              <div>
                <Label htmlFor="groupTitle" className="text-sm font-medium">
                  그룹 제목
                </Label>
                <Input
                  id="groupTitle"
                  value={localInputs.title}
                  onChange={(e) => {
                    const newValue = e.target.value;
                    setLocalInputs((prev) => ({ ...prev, title: newValue }));
                    onUpdateProperty("title", newValue);
                  }}
                  placeholder="그룹 제목"
                  className="mt-1"
                />
              </div>
            </div>
          </>
        )}

        {selectedComponent.type === "area" && (
          <>
            <Separator />

            {/* 영역 설정 */}
            <div className="space-y-3">
              <div className="flex items-center space-x-2">
                <Settings className="text-muted-foreground h-4 w-4" />
                <h4 className="font-medium text-gray-900">영역 설정</h4>
              </div>

              <div>
                <Label htmlFor="areaTitle" className="text-sm font-medium">
                  영역 제목
                </Label>
                <Input
                  id="areaTitle"
                  value={localInputs.title}
                  onChange={(e) => {
                    const newValue = e.target.value;
                    setLocalInputs((prev) => ({ ...prev, title: newValue }));
                    onUpdateProperty("title", newValue);
                  }}
                  placeholder="영역 제목"
                  className="mt-1"
                />
              </div>

              <div>
                <Label htmlFor="areaDescription" className="text-sm font-medium">
                  영역 설명
                </Label>
                <Input
                  id="areaDescription"
                  value={localInputs.description}
                  onChange={(e) => {
                    const newValue = e.target.value;
                    setLocalInputs((prev) => ({ ...prev, description: newValue }));
                    onUpdateProperty("description", newValue);
                  }}
                  placeholder="영역 설명 (선택사항)"
                  className="mt-1"
                />
              </div>

              <div>
                <Label htmlFor="layoutType" className="text-sm font-medium">
                  레이아웃 타입
                </Label>
                <select
                  className="focus:border-primary mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:ring-1 focus:ring-blue-500 focus:outline-none"
                  value={(selectedComponent as AreaComponent).layoutType}
                  onChange={(e) => onUpdateProperty("layoutType", e.target.value as AreaLayoutType)}
                >
                  <option value="box">기본 박스</option>
                  <option value="card">카드</option>
                  <option value="panel">패널 (헤더 포함)</option>
                  <option value="section">섹션</option>
                  <option value="grid">그리드</option>
                  <option value="flex-row">가로 플렉스</option>
                  <option value="flex-column">세로 플렉스</option>
                  <option value="sidebar">사이드바</option>
                  <option value="header-content">헤더-컨텐츠</option>
                  <option value="tabs">탭</option>
                  <option value="accordion">아코디언</option>
                </select>
              </div>

              {/* 레이아웃별 상세 설정 */}
              {(selectedComponent as AreaComponent).layoutType === "grid" && (
                <div className="space-y-2 rounded-md border p-3">
                  <h5 className="text-sm font-medium">그리드 설정</h5>
                  <div className="grid grid-cols-2 gap-2">
                    <div>
                      <Label className="text-xs">컬럼 수</Label>
                      <Input
                        type="number"
                        min="1"
                        max="12"
                        value={(selectedComponent as AreaComponent).layoutConfig?.gridColumns || 3}
                        onChange={(e) => {
                          const value = Number(e.target.value);
                          onUpdateProperty("layoutConfig.gridColumns", value);
                        }}
                        className="mt-1"
                      />
                    </div>
                    <div>
                      <Label className="text-xs">간격 (px)</Label>
                      <Input
                        type="number"
                        min="0"
                        value={(selectedComponent as AreaComponent).layoutConfig?.gridGap || 16}
                        onChange={(e) => {
                          const value = Number(e.target.value);
                          onUpdateProperty("layoutConfig.gridGap", value);
                        }}
                        className="mt-1"
                      />
                    </div>
                  </div>
                </div>
              )}

              {((selectedComponent as AreaComponent).layoutType === "flex-row" ||
                (selectedComponent as AreaComponent).layoutType === "flex-column") && (
                <div className="space-y-2 rounded-md border p-3">
                  <h5 className="text-sm font-medium">플렉스 설정</h5>
                  <div>
                    <Label className="text-xs">정렬 방식</Label>
                    <select
                      className="focus:border-primary mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:ring-1 focus:ring-blue-500 focus:outline-none"
                      value={(selectedComponent as AreaComponent).layoutConfig?.justifyContent || "flex-start"}
                      onChange={(e) => onUpdateProperty("layoutConfig.justifyContent", e.target.value)}
                    >
                      <option value="flex-start">시작</option>
                      <option value="flex-end">끝</option>
                      <option value="center">가운데</option>
                      <option value="space-between">양끝 정렬</option>
                      <option value="space-around">균등 분배</option>
                      <option value="space-evenly">균등 간격</option>
                    </select>
                  </div>
                  <div>
                    <Label className="text-xs">간격 (px)</Label>
                    <Input
                      type="number"
                      min="0"
                      value={(selectedComponent as AreaComponent).layoutConfig?.gap || 16}
                      onChange={(e) => {
                        const value = Number(e.target.value);
                        onUpdateProperty("layoutConfig.gap", value);
                      }}
                      className="mt-1"
                    />
                  </div>
                </div>
              )}

              {(selectedComponent as AreaComponent).layoutType === "sidebar" && (
                <div className="space-y-2 rounded-md border p-3">
                  <h5 className="text-sm font-medium">사이드바 설정</h5>
                  <div>
                    <Label className="text-xs">사이드바 위치</Label>
                    <select
                      className="focus:border-primary mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:ring-1 focus:ring-blue-500 focus:outline-none"
                      value={(selectedComponent as AreaComponent).layoutConfig?.sidebarPosition || "left"}
                      onChange={(e) => onUpdateProperty("layoutConfig.sidebarPosition", e.target.value)}
                    >
                      <option value="left">왼쪽</option>
                      <option value="right">오른쪽</option>
                    </select>
                  </div>
                  <div>
                    <Label className="text-xs">사이드바 너비 (px)</Label>
                    <Input
                      type="number"
                      min="100"
                      value={(selectedComponent as AreaComponent).layoutConfig?.sidebarWidth || 200}
                      onChange={(e) => {
                        const value = Number(e.target.value);
                        onUpdateProperty("layoutConfig.sidebarWidth", value);
                      }}
                      className="mt-1"
                    />
                  </div>
                </div>
              )}
            </div>
          </>
        )}
      </div>
    </div>
  );
};

// React.memo로 감싸서 불필요한 리렌더링 방지
export const PropertiesPanel = React.memo(PropertiesPanelComponent, (prevProps, nextProps) => {
  // 선택된 컴포넌트 ID가 다르면 리렌더링
  if (prevProps.selectedComponent?.id !== nextProps.selectedComponent?.id) {
    return false;
  }

  // 선택된 컴포넌트가 없는 상태에서 있는 상태로 변경되거나 그 반대인 경우
  if (!prevProps.selectedComponent !== !nextProps.selectedComponent) {
    return false;
  }

  // 테이블 목록이 변경되면 리렌더링
  if (prevProps.tables.length !== nextProps.tables.length) {
    return false;
  }

  // 그룹 관련 props가 변경되면 리렌더링
  if (prevProps.canGroup !== nextProps.canGroup || prevProps.canUngroup !== nextProps.canUngroup) {
    return false;
  }

  // 그 외의 경우는 리렌더링하지 않음
  return true;
});

export default PropertiesPanel;
