"use client";

/**
 * V2Button 설정 패널
 * 토스식 단계별 UX: 액션 유형 카드 선택 -> 표시 모드 카드 -> 액션별 세부 설정 -> 고급 설정(접힘)
 */

import React, { useState, useEffect, useMemo, useCallback } from "react";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { Button } from "@/components/ui/button";
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from "@/components/ui/collapsible";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command";
import { Separator } from "@/components/ui/separator";
import {
  Save,
  Trash2,
  Pencil,
  ArrowRight,
  Maximize2,
  SendHorizontal,
  Download,
  Upload,
  Zap,
  Settings,
  ChevronDown,
  Check,
  Plus,
  X,
  Type,
  Image,
  Columns,
  ScanLine,
  Truck,
  Send,
  Copy,
  FileSpreadsheet,
  ChevronsUpDown,
  Info,
  Workflow,
} from "lucide-react";
import { icons as allLucideIcons } from "lucide-react";
import { cn } from "@/lib/utils";
import { apiClient } from "@/lib/api/client";
import {
  actionIconMap,
  noIconActions,
  NO_ICON_MESSAGE,
  iconSizePresets,
  getLucideIcon,
  addToIconMap,
  getDefaultIconForAction,
  sanitizeSvg,
} from "@/lib/button-icon-map";
import { ImprovedButtonControlConfigPanel } from "@/components/screen/config-panels/ImprovedButtonControlConfigPanel";
import { FlowVisibilityConfigPanel } from "@/components/screen/config-panels/FlowVisibilityConfigPanel";
import type { ComponentData } from "@/types/screen";

// ─── 액션 유형 카드 정의 ───
const ACTION_TYPE_CARDS = [
  {
    value: "save",
    icon: Save,
    title: "저장",
    description: "데이터를 저장해요",
  },
  {
    value: "delete",
    icon: Trash2,
    title: "삭제",
    description: "데이터를 삭제해요",
  },
  {
    value: "edit",
    icon: Pencil,
    title: "편집",
    description: "데이터를 수정해요",
  },
  {
    value: "modal",
    icon: Maximize2,
    title: "모달 열기",
    description: "팝업 화면을 열어요",
  },
  {
    value: "navigate",
    icon: ArrowRight,
    title: "페이지 이동",
    description: "다른 화면으로 이동해요",
  },
  {
    value: "transferData",
    icon: SendHorizontal,
    title: "데이터 전달",
    description: "다른 테이블로 전달해요",
  },
  {
    value: "excel_download",
    icon: Download,
    title: "엑셀 다운로드",
    description: "데이터를 엑셀로 받아요",
  },
  {
    value: "excel_upload",
    icon: Upload,
    title: "엑셀 업로드",
    description: "엑셀 파일을 올려요",
  },
  {
    value: "approval",
    icon: Check,
    title: "결재 요청",
    description: "결재를 요청해요",
  },
  {
    value: "control",
    icon: Settings,
    title: "제어 흐름",
    description: "흐름을 제어해요",
  },
  {
    value: "copy",
    icon: Copy,
    title: "복사",
    description: "데이터를 복사해요",
  },
  {
    value: "barcode_scan",
    icon: ScanLine,
    title: "바코드 스캔",
    description: "바코드를 스캔해요",
  },
  {
    value: "operation_control",
    icon: Truck,
    title: "운행알림/종료",
    description: "운행을 관리해요",
  },
  {
    value: "multi_table_excel_upload",
    icon: FileSpreadsheet,
    title: "다중 엑셀 업로드",
    description: "여러 테이블에 올려요",
  },
] as const;

// ─── 표시 모드 카드 정의 ───
const DISPLAY_MODE_CARDS = [
  {
    value: "text" as const,
    icon: Type,
    title: "텍스트",
    description: "텍스트만 표시",
  },
  {
    value: "icon" as const,
    icon: Image,
    title: "아이콘",
    description: "아이콘만 표시",
  },
  {
    value: "icon-text" as const,
    icon: Columns,
    title: "아이콘+텍스트",
    description: "둘 다 표시",
  },
] as const;

// ─── 버튼 변형 옵션 ───
const VARIANT_OPTIONS = [
  { value: "primary", label: "기본 (Primary)" },
  { value: "secondary", label: "보조 (Secondary)" },
  { value: "danger", label: "위험 (Danger)" },
] as const;

interface ScreenOption {
  id: number;
  name: string;
  description?: string;
}

interface V2ButtonConfigPanelProps {
  config: Record<string, any>;
  onChange: (config: Record<string, any>) => void;
  component?: ComponentData;
  currentComponent?: ComponentData;
  onUpdateProperty?: (path: string, value: any) => void;
  allComponents?: ComponentData[];
  currentTableName?: string;
  screenTableName?: string;
  currentScreenCompanyCode?: string;
  [key: string]: any;
}

export const V2ButtonConfigPanel: React.FC<V2ButtonConfigPanelProps> = ({
  config,
  onChange,
  component,
  currentComponent,
  onUpdateProperty,
  allComponents = [],
  currentTableName,
  screenTableName,
  currentScreenCompanyCode,
}) => {
  const effectiveComponent = component || currentComponent;
  const effectiveTableName = currentTableName || screenTableName;
  const actionType = String(config.action?.type || "save");
  const displayMode = (config.displayMode as "text" | "icon" | "icon-text") || "text";
  const variant = config.variant || "primary";
  const buttonText = config.text !== undefined ? config.text : "버튼";

  // 아이콘 상태
  const [selectedIcon, setSelectedIcon] = useState<string>(config.icon?.name || "");
  const [selectedIconType, setSelectedIconType] = useState<"lucide" | "svg">(
    config.icon?.type || "lucide"
  );
  const [iconSize, setIconSize] = useState<string>(config.icon?.size || "보통");

  // UI 상태
  const [iconSectionOpen, setIconSectionOpen] = useState(false);
  const [advancedOpen, setAdvancedOpen] = useState(false);
  const [lucideSearchOpen, setLucideSearchOpen] = useState(false);
  const [lucideSearchTerm, setLucideSearchTerm] = useState("");
  const [svgPasteOpen, setSvgPasteOpen] = useState(false);
  const [svgInput, setSvgInput] = useState("");
  const [svgName, setSvgName] = useState("");
  const [svgError, setSvgError] = useState("");

  // 모달 관련
  const [screens, setScreens] = useState<ScreenOption[]>([]);
  const [screensLoading, setScreensLoading] = useState(false);
  const [modalScreenOpen, setModalScreenOpen] = useState(false);
  const [modalSearchTerm, setModalSearchTerm] = useState("");

  // 데이터 전달 필드 매핑 관련
  const [availableTables, setAvailableTables] = useState<Array<{ name: string; label: string }>>([]);
  const [mappingSourceColumnsMap, setMappingSourceColumnsMap] = useState<Record<string, Array<{ name: string; label: string }>>>({});
  const [mappingTargetColumns, setMappingTargetColumns] = useState<Array<{ name: string; label: string }>>([]);
  const [fieldMappingOpen, setFieldMappingOpen] = useState(false);
  const [activeMappingGroupIndex, setActiveMappingGroupIndex] = useState(0);

  const showIconSettings = displayMode === "icon" || displayMode === "icon-text";
  const currentActionIcons = actionIconMap[actionType] || [];
  const isNoIconAction = noIconActions.has(actionType);
  const customIcons: string[] = config.customIcons || [];
  const customSvgIcons: Array<{ name: string; svg: string }> = config.customSvgIcons || [];

  // 플로우 위젯 존재 여부
  const hasFlowWidget = useMemo(() => {
    return allComponents.some((comp: any) => {
      const compType = comp.componentType || comp.widgetType || "";
      return compType === "flow-widget" || compType?.toLowerCase().includes("flow");
    });
  }, [allComponents]);

  // config 업데이트 헬퍼
  const updateConfig = useCallback(
    (field: string, value: any) => {
      onChange({ ...config, [field]: value });
    },
    [config, onChange]
  );

  const updateActionConfig = useCallback(
    (field: string, value: any) => {
      const currentAction = config.action || {};
      onChange({
        ...config,
        action: { ...currentAction, [field]: value },
      });
    },
    [config, onChange]
  );

  // 기존 서브패널(ImprovedButtonControlConfigPanel 등)이 webTypeConfig.* 경로로 쓰므로
  // 항상 config 기반 onChange로 통일 (onUpdateProperty는 V2 경로 불일치 문제 있음)
  const handleUpdateProperty = useCallback(
    (path: string, value: any) => {
      const normalizedPath = path
        .replace(/^componentConfig\./, "")
        .replace(/^webTypeConfig\./, "");
      const parts = normalizedPath.split(".");
      const newConfig = { ...config };
      let current: any = newConfig;
      for (let i = 0; i < parts.length - 1; i++) {
        if (!current[parts[i]]) current[parts[i]] = {};
        current[parts[i]] = { ...current[parts[i]] };
        current = current[parts[i]];
      }
      current[parts[parts.length - 1]] = value;
      onChange(newConfig);
    },
    [config, onChange]
  );

  // prop 변경 시 아이콘 상태 동기화
  useEffect(() => {
    setSelectedIcon(config.icon?.name || "");
    setSelectedIconType(config.icon?.type || "lucide");
    setIconSize(config.icon?.size || "보통");
  }, [config.icon?.name, config.icon?.type, config.icon?.size]);

  // 테이블 목록 로드 (데이터 전달 액션용)
  useEffect(() => {
    if (actionType !== "transferData") return;
    if (availableTables.length > 0) return;

    const loadTables = async () => {
      try {
        const response = await apiClient.get("/table-management/tables");
        if (response.data.success && response.data.data) {
          const tables = response.data.data.map((t: any) => ({
            name: t.tableName || t.name,
            label: t.displayName || t.tableLabel || t.label || t.tableName || t.name,
          }));
          setAvailableTables(tables);
        }
      } catch {
        setAvailableTables([]);
      }
    };
    loadTables();
  }, [actionType, availableTables.length]);

  // 테이블 컬럼 로드 헬퍼
  const loadTableColumns = useCallback(async (tableName: string): Promise<Array<{ name: string; label: string }>> => {
    try {
      const response = await apiClient.get(`/table-management/tables/${tableName}/columns`);
      if (response.data.success) {
        let columnData = response.data.data;
        if (!Array.isArray(columnData) && columnData?.columns) columnData = columnData.columns;
        if (!Array.isArray(columnData) && columnData?.data) columnData = columnData.data;
        if (Array.isArray(columnData)) {
          return columnData.map((col: any) => ({
            name: col.name || col.columnName,
            label: col.displayName || col.label || col.columnLabel || col.name || col.columnName,
          }));
        }
      }
    } catch { /* ignore */ }
    return [];
  }, []);

  // 멀티 테이블 매핑: 소스/타겟 테이블 컬럼 로드
  useEffect(() => {
    if (actionType !== "transferData") return;

    const multiTableMappings: Array<{ sourceTable: string }> = config.action?.dataTransfer?.multiTableMappings || [];
    const targetTable = config.action?.dataTransfer?.targetTable;

    const loadAll = async () => {
      const sourceTableNames = multiTableMappings.map((m) => m.sourceTable).filter(Boolean);
      const newMap: Record<string, Array<{ name: string; label: string }>> = {};
      for (const tbl of sourceTableNames) {
        if (!mappingSourceColumnsMap[tbl]) {
          newMap[tbl] = await loadTableColumns(tbl);
        }
      }
      if (Object.keys(newMap).length > 0) {
        setMappingSourceColumnsMap((prev) => ({ ...prev, ...newMap }));
      }

      if (targetTable) {
        const cols = await loadTableColumns(targetTable);

        try {
          const fullResponse = await apiClient.get(`/table-management/tables/${targetTable}/columns`);
          let fullColumnData = fullResponse.data?.data;
          if (!Array.isArray(fullColumnData) && fullColumnData?.columns) fullColumnData = fullColumnData.columns;
          if (!Array.isArray(fullColumnData) && fullColumnData?.data) fullColumnData = fullColumnData.data;

          if (Array.isArray(fullColumnData)) {
            const refTableSet = new Set<string>();
            fullColumnData.forEach((col: any) => {
              const inputType = col.inputType || col.input_type;
              if (inputType !== "entity") return;
              let refTable = col.referenceTable || col.reference_table;
              if (!refTable && col.detailSettings) {
                try {
                  const ds = typeof col.detailSettings === "string" ? JSON.parse(col.detailSettings) : col.detailSettings;
                  refTable = ds?.referenceTable;
                } catch { /* ignore */ }
              }
              if (refTable) refTableSet.add(refTable);
            });

            const targetColumnNames = new Set(cols.map((c) => c.name));
            for (const refTable of refTableSet) {
              const refCols = await loadTableColumns(refTable);
              const refTableLabel = availableTables.find((t) => t.name === refTable)?.label || refTable;
              refCols.forEach((rc) => {
                if (!targetColumnNames.has(rc.name)) {
                  cols.push({
                    name: rc.name,
                    label: `${rc.label} [${refTableLabel}]`,
                  });
                }
              });
            }
          }
        } catch { /* ignore */ }

        setMappingTargetColumns(cols);
      } else {
        setMappingTargetColumns([]);
      }
    };
    loadAll();
  }, [actionType, config.action?.dataTransfer?.multiTableMappings, config.action?.dataTransfer?.targetTable, availableTables, loadTableColumns]);

  // 화면 목록 로드 (모달/편집/네비게이트 액션용)
  useEffect(() => {
    if (actionType !== "modal" && actionType !== "navigate" && actionType !== "edit") return;
    if (screens.length > 0) return;

    const loadScreens = async () => {
      setScreensLoading(true);
      try {
        const response = await apiClient.get("/screen-management/screens?size=1000");
        if (response.data.success && response.data.data) {
          const screenList = response.data.data.map((s: any) => ({
            id: s.id || s.screenId,
            name: s.name || s.screenName,
            description: s.description || "",
          }));
          setScreens(screenList);
        }
      } catch {
        setScreens([]);
      } finally {
        setScreensLoading(false);
      }
    };
    loadScreens();
  }, [actionType, screens.length]);

  // 아이콘 선택 핸들러
  const handleSelectIcon = (iconName: string, iconType: "lucide" | "svg" = "lucide") => {
    setSelectedIcon(iconName);
    setSelectedIconType(iconType);
    updateConfig("icon", {
      name: iconName,
      type: iconType,
      size: iconSize,
    });
  };

  const revertToDefaultIcon = () => {
    const def = getDefaultIconForAction(actionType);
    handleSelectIcon(def.name, def.type);
  };

  // 액션 유형 변경 핸들러
  const handleActionTypeChange = (newType: string) => {
    const currentAction = config.action || {};
    onChange({
      ...config,
      action: { ...currentAction, type: newType },
    });

    // 아이콘이 새 액션 추천에 없으면 초기화
    const newActionIcons = actionIconMap[newType] || [];
    if (selectedIcon && selectedIconType === "lucide" && !newActionIcons.includes(selectedIcon) && !customIcons.includes(selectedIcon)) {
      setSelectedIcon("");
      updateConfig("icon", undefined);
    }
  };

  // componentData 생성 (기존 패널 재사용용)
  // effectiveComponent가 있어도 config 변경분을 반드시 반영해야 토글 등이 동작함
  const componentData = useMemo(() => {
    if (effectiveComponent) {
      return {
        ...effectiveComponent,
        componentConfig: config,
        webTypeConfig: config,
      } as ComponentData;
    }
    return {
      id: "virtual",
      type: "widget" as const,
      position: { x: 0, y: 0 },
      size: { width: 120, height: 40 },
      componentConfig: config,
      webTypeConfig: config,
      componentType: "v2-button-primary",
    } as ComponentData;
  }, [effectiveComponent, config]);

  return (
    <div className="space-y-4">
      {/* ─── 1단계: 버튼 액션 유형 선택 (가장 중요) ─── */}
      <div className="space-y-2">
        <p className="text-sm font-medium">이 버튼은 어떤 동작을 하나요?</p>
        <div className="grid grid-cols-3 gap-2">
          {ACTION_TYPE_CARDS.map((card) => {
            const Icon = card.icon;
            const isSelected = actionType === card.value;
            return (
              <button
                key={card.value}
                type="button"
                onClick={() => handleActionTypeChange(card.value)}
                className={cn(
                  "flex flex-col items-center justify-center rounded-lg border p-2 text-center transition-all min-h-[68px]",
                  isSelected
                    ? "border-primary bg-primary/5 ring-1 ring-primary/20"
                    : "border-border hover:border-primary/50 hover:bg-muted/50"
                )}
              >
                <Icon className={cn("h-4 w-4 mb-1", isSelected ? "text-primary" : "text-muted-foreground")} />
                <span className="text-[11px] font-medium leading-tight">{card.title}</span>
                <span className="text-[9px] text-muted-foreground leading-tight mt-0.5">{card.description}</span>
              </button>
            );
          })}
        </div>
      </div>

      <Separator />

      {/* ─── 2단계: 표시 모드 선택 ─── */}
      <div className="space-y-2">
        <p className="text-sm font-medium">버튼을 어떻게 표시할까요?</p>
        <div className="grid grid-cols-3 gap-2">
          {DISPLAY_MODE_CARDS.map((card) => {
            const Icon = card.icon;
            const isSelected = displayMode === card.value;
            return (
              <button
                key={card.value}
                type="button"
                onClick={() => {
                  updateConfig("displayMode", card.value);
                  if ((card.value === "icon" || card.value === "icon-text") && !selectedIcon) {
                    revertToDefaultIcon();
                  }
                }}
                className={cn(
                  "flex flex-col items-center justify-center rounded-lg border p-2.5 text-center transition-all",
                  isSelected
                    ? "border-primary bg-primary/5 ring-1 ring-primary/20"
                    : "border-border hover:border-primary/50 hover:bg-muted/50"
                )}
              >
                <Icon className={cn("h-4 w-4 mb-1", isSelected ? "text-primary" : "text-muted-foreground")} />
                <span className="text-xs font-medium">{card.title}</span>
              </button>
            );
          })}
        </div>
      </div>

      {/* ─── 버튼 텍스트 ─── */}
      {(displayMode === "text" || displayMode === "icon-text") && (
        <div>
          <Label htmlFor="btn-text" className="mb-1.5 text-xs">
            버튼 텍스트
          </Label>
          <Input
            id="btn-text"
            value={buttonText}
            onChange={(e) => updateConfig("text", e.target.value)}
            placeholder="버튼에 표시할 텍스트"
            className="h-8 text-sm"
          />
        </div>
      )}

      {/* ─── 버튼 변형 ─── */}
      <div>
        <Label className="mb-1.5 text-xs">버튼 스타일</Label>
        <Select value={variant} onValueChange={(v) => updateConfig("variant", v)}>
          <SelectTrigger className="h-8 text-sm">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            {VARIANT_OPTIONS.map((opt) => (
              <SelectItem key={opt.value} value={opt.value}>
                {opt.label}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>

      <Separator />

      {/* ─── 3단계: 액션별 세부 설정 ─── */}
      <ActionDetailSection
        actionType={actionType}
        config={config}
        updateConfig={updateConfig}
        updateActionConfig={updateActionConfig}
        screens={screens}
        screensLoading={screensLoading}
        modalScreenOpen={modalScreenOpen}
        setModalScreenOpen={setModalScreenOpen}
        modalSearchTerm={modalSearchTerm}
        setModalSearchTerm={setModalSearchTerm}
        currentTableName={effectiveTableName}
        allComponents={allComponents}
        handleUpdateProperty={handleUpdateProperty}
      />

      {/* ─── 아이콘 설정 (접기) ─── */}
      {showIconSettings && (
        <Collapsible open={iconSectionOpen} onOpenChange={setIconSectionOpen}>
          <CollapsibleTrigger asChild>
            <button
              type="button"
              className="flex w-full items-center justify-between rounded-lg border bg-muted/30 px-4 py-2.5 text-left transition-colors hover:bg-muted/50"
            >
              <div className="flex items-center gap-2">
                <Image className="h-4 w-4 text-muted-foreground" />
                <span className="text-sm font-medium">아이콘 설정</span>
              </div>
              <ChevronDown
                className={cn(
                  "h-4 w-4 text-muted-foreground transition-transform duration-200",
                  iconSectionOpen && "rotate-180"
                )}
              />
            </button>
          </CollapsibleTrigger>
          <CollapsibleContent>
            <div className="rounded-b-lg border border-t-0 p-4 space-y-3">
              <IconSettingsSection
                actionType={actionType}
                isNoIconAction={isNoIconAction}
                currentActionIcons={currentActionIcons}
                selectedIcon={selectedIcon}
                selectedIconType={selectedIconType}
                iconSize={iconSize}
                displayMode={displayMode}
                iconTextPosition={config.iconTextPosition || "right"}
                iconGap={config.iconGap ?? 6}
                customIcons={customIcons}
                customSvgIcons={customSvgIcons}
                lucideSearchOpen={lucideSearchOpen}
                setLucideSearchOpen={setLucideSearchOpen}
                lucideSearchTerm={lucideSearchTerm}
                setLucideSearchTerm={setLucideSearchTerm}
                svgPasteOpen={svgPasteOpen}
                setSvgPasteOpen={setSvgPasteOpen}
                svgInput={svgInput}
                setSvgInput={setSvgInput}
                svgName={svgName}
                setSvgName={setSvgName}
                svgError={svgError}
                setSvgError={setSvgError}
                onSelectIcon={handleSelectIcon}
                onRevertToDefault={revertToDefaultIcon}
                onIconSizeChange={(preset) => {
                  setIconSize(preset);
                  if (selectedIcon) {
                    updateConfig("icon", { ...config.icon, size: preset });
                  }
                }}
                onIconTextPositionChange={(pos) => updateConfig("iconTextPosition", pos)}
                onIconGapChange={(gap) => updateConfig("iconGap", gap)}
                onCustomIconsChange={(icons) => updateConfig("customIcons", icons)}
                onCustomSvgIconsChange={(icons) => updateConfig("customSvgIcons", icons)}
              />
            </div>
          </CollapsibleContent>
        </Collapsible>
      )}

      {/* ─── 고급 설정 (접기) ─── */}
      <Collapsible open={advancedOpen} onOpenChange={setAdvancedOpen}>
        <CollapsibleTrigger asChild>
          <button
            type="button"
            className="flex w-full items-center justify-between rounded-lg border bg-muted/30 px-4 py-2.5 text-left transition-colors hover:bg-muted/50"
          >
            <div className="flex items-center gap-2">
              <Settings className="h-4 w-4 text-muted-foreground" />
              <span className="text-sm font-medium">고급 설정</span>
            </div>
            <ChevronDown
              className={cn(
                "h-4 w-4 text-muted-foreground transition-transform duration-200",
                advancedOpen && "rotate-180"
              )}
            />
          </button>
        </CollapsibleTrigger>
        <CollapsibleContent>
          <div className="rounded-b-lg border border-t-0 p-4 space-y-4">
            {/* 행 선택 활성화 */}
            <div className="space-y-3">
              <div className="flex items-center justify-between">
                <div className="space-y-0.5">
                  <p className="text-sm font-medium">행 선택 시에만 활성화</p>
                  <p className="text-[11px] text-muted-foreground">
                    테이블에서 행을 선택해야만 버튼이 활성화돼요
                  </p>
                </div>
                <Switch
                  checked={config.action?.requireRowSelection || false}
                  onCheckedChange={(checked) => updateActionConfig("requireRowSelection", checked)}
                />
              </div>

              {config.action?.requireRowSelection && (
                <div className="ml-4 space-y-2 border-l-2 border-primary/20 pl-3">
                  <div>
                    <Label className="text-xs">선택 데이터 소스</Label>
                    <Select
                      value={config.action?.rowSelectionSource || "auto"}
                      onValueChange={(v) => updateActionConfig("rowSelectionSource", v)}
                    >
                      <SelectTrigger className="h-7 text-xs">
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="auto">자동 감지 (권장)</SelectItem>
                        <SelectItem value="tableList">테이블 리스트</SelectItem>
                        <SelectItem value="splitPanelLeft">분할 패널 좌측</SelectItem>
                        <SelectItem value="flowWidget">플로우 위젯</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>

                  <div className="flex items-center justify-between">
                    <div>
                      <p className="text-xs">다중 선택 허용</p>
                      <p className="text-[10px] text-muted-foreground">여러 행 선택 시에도 활성화</p>
                    </div>
                    <Switch
                      checked={config.action?.allowMultiRowSelection ?? true}
                      onCheckedChange={(checked) => updateActionConfig("allowMultiRowSelection", checked)}
                    />
                  </div>
                </div>
              )}
            </div>

            {/* 데이터 전달 필드 매핑 (transferData 액션 전용) */}
            {actionType === "transferData" && (
              <>
                <Separator />
                <TransferDataFieldMappingSection
                  config={config}
                  onChange={onChange}
                  availableTables={availableTables}
                  mappingSourceColumnsMap={mappingSourceColumnsMap}
                  setMappingSourceColumnsMap={setMappingSourceColumnsMap}
                  mappingTargetColumns={mappingTargetColumns}
                  fieldMappingOpen={fieldMappingOpen}
                  setFieldMappingOpen={setFieldMappingOpen}
                  activeMappingGroupIndex={activeMappingGroupIndex}
                  setActiveMappingGroupIndex={setActiveMappingGroupIndex}
                  loadTableColumns={loadTableColumns}
                />
              </>
            )}

            {/* 제어 기능 */}
            {actionType !== "excel_upload" && actionType !== "multi_table_excel_upload" && (
              <>
                <Separator />
                <ImprovedButtonControlConfigPanel
                  component={componentData}
                  onUpdateProperty={handleUpdateProperty}
                />
              </>
            )}

            {/* 플로우 단계별 표시 제어 */}
            {hasFlowWidget && (
              <>
                <Separator />
                <FlowVisibilityConfigPanel
                  component={componentData}
                  allComponents={allComponents}
                  onUpdateProperty={handleUpdateProperty}
                />
              </>
            )}
          </div>
        </CollapsibleContent>
      </Collapsible>
    </div>
  );
};

// ─── 액션별 세부 설정 서브 컴포넌트 ───
const ActionDetailSection: React.FC<{
  actionType: string;
  config: Record<string, any>;
  updateConfig: (field: string, value: any) => void;
  updateActionConfig: (field: string, value: any) => void;
  screens: ScreenOption[];
  screensLoading: boolean;
  modalScreenOpen: boolean;
  setModalScreenOpen: (open: boolean) => void;
  modalSearchTerm: string;
  setModalSearchTerm: (term: string) => void;
  currentTableName?: string;
  allComponents?: ComponentData[];
  handleUpdateProperty?: (path: string, value: any) => void;
}> = ({
  actionType,
  config,
  updateConfig,
  updateActionConfig,
  screens,
  screensLoading,
  modalScreenOpen,
  setModalScreenOpen,
  modalSearchTerm,
  setModalSearchTerm,
  currentTableName,
  allComponents = [],
  handleUpdateProperty,
}) => {
  const action = config.action || {};

  // 성공/에러 메시지 (모든 액션 공통)
  const commonMessageSection = (
    <div className="space-y-2">
      <div>
        <Label className="text-xs">성공 메시지</Label>
        <Input
          value={action.successMessage || ""}
          onChange={(e) => updateActionConfig("successMessage", e.target.value)}
          placeholder="처리되었습니다."
          className="h-7 text-xs"
        />
      </div>
      <div>
        <Label className="text-xs">에러 메시지</Label>
        <Input
          value={action.errorMessage || ""}
          onChange={(e) => updateActionConfig("errorMessage", e.target.value)}
          placeholder="처리 중 오류가 발생했습니다."
          className="h-7 text-xs"
        />
      </div>
    </div>
  );

  switch (actionType) {
    case "save":
    case "delete":
    case "quickInsert":
      return (
        <div className="rounded-lg border bg-muted/30 p-4 space-y-3">
          <div className="flex items-center gap-2">
            <Info className="h-4 w-4 text-primary" />
            <span className="text-sm font-medium">
              {actionType === "save" && "저장 설정"}
              {actionType === "delete" && "삭제 설정"}
              {actionType === "quickInsert" && "즉시 저장 설정"}
            </span>
          </div>
          {commonMessageSection}

          {actionType === "delete" && (
            <div className="flex items-center justify-between">
              <div>
                <p className="text-xs font-medium">삭제 확인 팝업</p>
                <p className="text-[10px] text-muted-foreground">삭제 전 확인 대화상자를 표시해요</p>
              </div>
              <Switch
                checked={action.confirmBeforeDelete !== false}
                onCheckedChange={(checked) => updateActionConfig("confirmBeforeDelete", checked)}
              />
            </div>
          )}
        </div>
      );

    case "edit":
      return (
        <div className="rounded-lg border bg-muted/30 p-4 space-y-3">
          <div className="flex items-center gap-2">
            <Pencil className="h-4 w-4 text-primary" />
            <span className="text-sm font-medium">편집 설정</span>
          </div>

          {/* 대상 화면 선택 */}
          <div>
            <Label className="text-xs">수정 폼 화면</Label>
            <Popover open={modalScreenOpen} onOpenChange={setModalScreenOpen}>
              <PopoverTrigger asChild>
                <Button
                  variant="outline"
                  role="combobox"
                  aria-expanded={modalScreenOpen}
                  className="h-8 w-full justify-between text-xs"
                  disabled={screensLoading}
                >
                  {screensLoading
                    ? "로딩 중..."
                    : action.targetScreenId
                      ? screens.find((s) => s.id === action.targetScreenId)?.name || `화면 #${action.targetScreenId}`
                      : "화면 선택"}
                  <ChevronsUpDown className="ml-2 h-3 w-3 shrink-0 opacity-50" />
                </Button>
              </PopoverTrigger>
              <PopoverContent className="p-0" style={{ width: "var(--radix-popover-trigger-width)" }} align="start">
                <Command shouldFilter={false}>
                  <CommandInput
                    placeholder="화면 검색..."
                    value={modalSearchTerm}
                    onValueChange={setModalSearchTerm}
                    className="text-xs"
                  />
                  <CommandList className="max-h-48">
                    <CommandEmpty className="py-3 text-xs">화면을 찾을 수 없습니다.</CommandEmpty>
                    <CommandGroup>
                      {screens
                        .filter((s) =>
                          !modalSearchTerm ||
                          s.name.toLowerCase().includes(modalSearchTerm.toLowerCase()) ||
                          s.description?.toLowerCase().includes(modalSearchTerm.toLowerCase()) ||
                          String(s.id).includes(modalSearchTerm)
                        )
                        .map((screen) => (
                          <CommandItem
                            key={screen.id}
                            value={String(screen.id)}
                            onSelect={() => {
                              updateActionConfig("targetScreenId", screen.id);
                              setModalScreenOpen(false);
                              setModalSearchTerm("");
                            }}
                            className="text-xs"
                          >
                            <Check
                              className={cn(
                                "mr-2 h-3 w-3",
                                action.targetScreenId === screen.id ? "opacity-100" : "opacity-0"
                              )}
                            />
                            <div className="flex flex-col">
                              <span className="font-medium">{screen.name}</span>
                              {screen.description && (
                                <span className="text-[10px] text-muted-foreground">{screen.description}</span>
                              )}
                            </div>
                          </CommandItem>
                        ))}
                    </CommandGroup>
                  </CommandList>
                </Command>
              </PopoverContent>
            </Popover>
          </div>

          {/* 편집 모드 선택 */}
          <div>
            <Label className="text-xs">편집 모드</Label>
            <Select
              value={action.editMode || "modal"}
              onValueChange={(value) => updateActionConfig("editMode", value)}
            >
              <SelectTrigger className="h-8 text-xs">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="modal" className="text-xs">모달로 열기</SelectItem>
                <SelectItem value="navigate" className="text-xs">페이지 이동</SelectItem>
              </SelectContent>
            </Select>
          </div>

          {/* 모달 모드일 때 추가 설정 */}
          {(action.editMode || "modal") === "modal" && (
            <>
              <div>
                <Label className="text-xs">모달 제목</Label>
                <Input
                  value={action.editModalTitle || ""}
                  onChange={(e) => updateActionConfig("editModalTitle", e.target.value)}
                  placeholder="데이터 수정"
                  className="h-7 text-xs"
                />
              </div>
              <div>
                <Label className="text-xs">모달 설명</Label>
                <Input
                  value={action.editModalDescription || ""}
                  onChange={(e) => updateActionConfig("editModalDescription", e.target.value)}
                  placeholder="모달 설명"
                  className="h-7 text-xs"
                />
              </div>
              <div>
                <Label className="text-xs">모달 크기</Label>
                <Select
                  value={action.modalSize || "lg"}
                  onValueChange={(value) => updateActionConfig("modalSize", value)}
                >
                  <SelectTrigger className="h-8 text-xs">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="sm" className="text-xs">작게 (sm)</SelectItem>
                    <SelectItem value="md" className="text-xs">보통 (md)</SelectItem>
                    <SelectItem value="lg" className="text-xs">크게 (lg)</SelectItem>
                    <SelectItem value="xl" className="text-xs">아주 크게 (xl)</SelectItem>
                    <SelectItem value="full" className="text-xs">전체 (full)</SelectItem>
                  </SelectContent>
                </Select>
              </div>
            </>
          )}

          {commonMessageSection}
        </div>
      );

    case "modal":
      return (
        <div className="rounded-lg border bg-muted/30 p-4 space-y-3">
          <div className="flex items-center gap-2">
            <Maximize2 className="h-4 w-4 text-primary" />
            <span className="text-sm font-medium">모달 설정</span>
          </div>

          {/* 대상 화면 선택 */}
          <div>
            <Label className="text-xs">대상 화면</Label>
            <Popover open={modalScreenOpen} onOpenChange={setModalScreenOpen}>
              <PopoverTrigger asChild>
                <Button
                  variant="outline"
                  role="combobox"
                  aria-expanded={modalScreenOpen}
                  className="h-8 w-full justify-between text-xs"
                  disabled={screensLoading}
                >
                  {screensLoading
                    ? "로딩 중..."
                    : action.targetScreenId
                      ? screens.find((s) => s.id === action.targetScreenId)?.name || `화면 #${action.targetScreenId}`
                      : "화면 선택"}
                  <ChevronsUpDown className="ml-2 h-3 w-3 shrink-0 opacity-50" />
                </Button>
              </PopoverTrigger>
              <PopoverContent className="p-0" style={{ width: "var(--radix-popover-trigger-width)" }} align="start">
                <Command shouldFilter={false}>
                  <CommandInput
                    placeholder="화면 검색..."
                    value={modalSearchTerm}
                    onValueChange={setModalSearchTerm}
                    className="text-xs"
                  />
                  <CommandList className="max-h-48">
                    <CommandEmpty className="py-3 text-xs">화면을 찾을 수 없습니다.</CommandEmpty>
                    <CommandGroup>
                      {screens
                        .filter((s) =>
                          !modalSearchTerm ||
                          s.name.toLowerCase().includes(modalSearchTerm.toLowerCase()) ||
                          s.description?.toLowerCase().includes(modalSearchTerm.toLowerCase()) ||
                          String(s.id).includes(modalSearchTerm)
                        )
                        .map((screen) => (
                          <CommandItem
                            key={screen.id}
                            value={String(screen.id)}
                            onSelect={() => {
                              updateActionConfig("targetScreenId", screen.id);
                              setModalScreenOpen(false);
                              setModalSearchTerm("");
                            }}
                            className="text-xs"
                          >
                            <Check
                              className={cn(
                                "mr-2 h-3 w-3",
                                action.targetScreenId === screen.id ? "opacity-100" : "opacity-0"
                              )}
                            />
                            <div className="flex flex-col">
                              <span className="font-medium">{screen.name}</span>
                              {screen.description && (
                                <span className="text-[10px] text-muted-foreground">{screen.description}</span>
                              )}
                            </div>
                          </CommandItem>
                        ))}
                    </CommandGroup>
                  </CommandList>
                </Command>
              </PopoverContent>
            </Popover>
          </div>

          {/* 모달 제목/설명 */}
          <div>
            <Label className="text-xs">모달 제목</Label>
            <Input
              value={action.modalTitle || ""}
              onChange={(e) => updateActionConfig("modalTitle", e.target.value)}
              placeholder="모달 제목"
              className="h-7 text-xs"
            />
          </div>
          <div>
            <Label className="text-xs">모달 설명</Label>
            <Input
              value={action.modalDescription || ""}
              onChange={(e) => updateActionConfig("modalDescription", e.target.value)}
              placeholder="모달 설명"
              className="h-7 text-xs"
            />
          </div>

          {/* 데이터 자동 전달 */}
          <div className="flex items-center justify-between">
            <div>
              <p className="text-xs font-medium">데이터 자동 전달</p>
              <p className="text-[10px] text-muted-foreground">선택된 행의 데이터를 모달에 전달해요</p>
            </div>
            <Switch
              checked={action.autoDetectDataSource || false}
              onCheckedChange={(checked) => updateActionConfig("autoDetectDataSource", checked)}
            />
          </div>

          {commonMessageSection}
        </div>
      );

    case "navigate":
      return (
        <div className="rounded-lg border bg-muted/30 p-4 space-y-3">
          <div className="flex items-center gap-2">
            <ArrowRight className="h-4 w-4 text-primary" />
            <span className="text-sm font-medium">이동 설정</span>
          </div>
          <div>
            <Label className="text-xs">이동 대상 URL</Label>
            <Input
              value={action.targetUrl || ""}
              onChange={(e) => updateActionConfig("targetUrl", e.target.value)}
              placeholder="/admin/example"
              className="h-7 text-xs"
            />
          </div>
          {commonMessageSection}
        </div>
      );

    case "excel_download":
      return (
        <div className="rounded-lg border bg-muted/30 p-4 space-y-3">
          <div className="flex items-center gap-2">
            <Download className="h-4 w-4 text-primary" />
            <span className="text-sm font-medium">엑셀 다운로드 설정</span>
          </div>

          <div className="flex items-center justify-between">
            <div>
              <p className="text-xs font-medium">현재 필터 적용</p>
              <p className="text-[10px] text-muted-foreground">검색 조건이 적용된 데이터만 다운로드</p>
            </div>
            <Switch
              checked={action.applyCurrentFilters !== false}
              onCheckedChange={(checked) => updateActionConfig("applyCurrentFilters", checked)}
            />
          </div>

          <div className="flex items-center justify-between">
            <div>
              <p className="text-xs font-medium">선택된 행만</p>
              <p className="text-[10px] text-muted-foreground">테이블에서 선택한 행만 다운로드</p>
            </div>
            <Switch
              checked={action.selectedRowsOnly || false}
              onCheckedChange={(checked) => updateActionConfig("selectedRowsOnly", checked)}
            />
          </div>

          {commonMessageSection}
        </div>
      );

    case "excel_upload":
    case "multi_table_excel_upload":
      return (
        <div className="rounded-lg border bg-muted/30 p-4 space-y-3">
          <div className="flex items-center gap-2">
            <Upload className="h-4 w-4 text-primary" />
            <span className="text-sm font-medium">
              {actionType === "multi_table_excel_upload" ? "다중 테이블 엑셀 업로드 설정" : "엑셀 업로드 설정"}
            </span>
          </div>
          {commonMessageSection}
        </div>
      );

    case "transferData":
      return (
        <div className="rounded-lg border bg-muted/30 p-4 space-y-3">
          <div className="flex items-center gap-2">
            <SendHorizontal className="h-4 w-4 text-primary" />
            <span className="text-sm font-medium">데이터 전달 설정</span>
          </div>

          {/* 소스 컴포넌트 선택 */}
          <div>
            <Label className="text-xs">
              소스 컴포넌트 <span className="text-destructive">*</span>
            </Label>
            <Select
              value={action.dataTransfer?.sourceComponentId || ""}
              onValueChange={(v) => {
                const dt = { ...action.dataTransfer, sourceComponentId: v };
                updateActionConfig("dataTransfer", dt);
              }}
            >
              <SelectTrigger className="h-8 text-xs">
                <SelectValue placeholder="데이터를 가져올 컴포넌트 선택" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="__auto__">
                  <span className="text-xs font-medium">자동 탐색 (현재 활성 테이블)</span>
                </SelectItem>
                {allComponents
                  .filter((comp: any) => {
                    const type = comp.componentType || comp.type || "";
                    return ["table-list", "repeater-field-group", "form-group", "data-table"].some((t) =>
                      type.includes(t)
                    );
                  })
                  .map((comp: any) => {
                    const compType = comp.componentType || comp.type || "unknown";
                    const compLabel = comp.label || comp.componentConfig?.title || comp.id;
                    return (
                      <SelectItem key={comp.id} value={comp.id}>
                        <div className="flex items-center gap-2">
                          <span className="text-xs font-medium">{compLabel}</span>
                          <span className="text-muted-foreground text-[10px]">({compType})</span>
                        </div>
                      </SelectItem>
                    );
                  })}
              </SelectContent>
            </Select>
          </div>

          {/* 타겟 타입 */}
          <div>
            <Label className="text-xs">
              타겟 타입 <span className="text-destructive">*</span>
            </Label>
            <Select
              value={action.dataTransfer?.targetType || "component"}
              onValueChange={(v) => {
                const dt = { ...action.dataTransfer, targetType: v };
                updateActionConfig("dataTransfer", dt);
              }}
            >
              <SelectTrigger className="h-8 text-xs">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="component">같은 화면의 컴포넌트</SelectItem>
                <SelectItem value="splitPanel">분할 패널 반대편 화면</SelectItem>
              </SelectContent>
            </Select>
          </div>

          {/* 타겟 컴포넌트 선택 */}
          {action.dataTransfer?.targetType === "component" && (
            <div>
              <Label className="text-xs">
                타겟 컴포넌트 <span className="text-destructive">*</span>
              </Label>
              <Select
                value={action.dataTransfer?.targetComponentId || ""}
                onValueChange={(v) => {
                  const dt = { ...action.dataTransfer, targetComponentId: v };
                  updateActionConfig("dataTransfer", dt);
                }}
              >
                <SelectTrigger className="h-8 text-xs">
                  <SelectValue placeholder="데이터를 받을 컴포넌트 선택" />
                </SelectTrigger>
                <SelectContent>
                  {allComponents
                    .filter((comp: any) => {
                      const type = comp.componentType || comp.type || "";
                      const isReceivable = ["table-list", "repeater-field-group", "form-group", "data-table"].some(
                        (t) => type.includes(t)
                      );
                      return isReceivable && comp.id !== action.dataTransfer?.sourceComponentId;
                    })
                    .map((comp: any) => {
                      const compType = comp.componentType || comp.type || "unknown";
                      const compLabel = comp.label || comp.componentConfig?.title || comp.id;
                      return (
                        <SelectItem key={comp.id} value={comp.id}>
                          <div className="flex items-center gap-2">
                            <span className="text-xs font-medium">{compLabel}</span>
                            <span className="text-muted-foreground text-[10px]">({compType})</span>
                          </div>
                        </SelectItem>
                      );
                    })}
                </SelectContent>
              </Select>
            </div>
          )}

          {/* 데이터 전달 모드 */}
          <div>
            <Label className="text-xs">데이터 전달 모드</Label>
            <Select
              value={action.dataTransfer?.mode || "append"}
              onValueChange={(v) => {
                const dt = { ...action.dataTransfer, mode: v };
                updateActionConfig("dataTransfer", dt);
              }}
            >
              <SelectTrigger className="h-8 text-xs">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="append">추가 (Append)</SelectItem>
                <SelectItem value="replace">교체 (Replace)</SelectItem>
                <SelectItem value="merge">병합 (Merge)</SelectItem>
              </SelectContent>
            </Select>
          </div>

          {/* 전달 후 초기화 */}
          <div className="flex items-center justify-between">
            <div>
              <p className="text-xs font-medium">전달 후 소스 선택 초기화</p>
              <p className="text-[10px] text-muted-foreground">데이터 전달 후 소스의 선택을 해제해요</p>
            </div>
            <Switch
              checked={action.dataTransfer?.clearAfterTransfer || false}
              onCheckedChange={(checked) => {
                const dt = { ...action.dataTransfer, clearAfterTransfer: checked };
                updateActionConfig("dataTransfer", dt);
              }}
            />
          </div>

          {/* 전달 전 확인 */}
          <div className="flex items-center justify-between">
            <div>
              <p className="text-xs font-medium">전달 전 확인 메시지</p>
              <p className="text-[10px] text-muted-foreground">전달 전 확인 다이얼로그를 표시해요</p>
            </div>
            <Switch
              checked={action.dataTransfer?.confirmBeforeTransfer || false}
              onCheckedChange={(checked) => {
                const dt = { ...action.dataTransfer, confirmBeforeTransfer: checked };
                updateActionConfig("dataTransfer", dt);
              }}
            />
          </div>

          {action.dataTransfer?.confirmBeforeTransfer && (
            <div>
              <Label className="text-xs">확인 메시지</Label>
              <Input
                value={action.dataTransfer?.confirmMessage || ""}
                onChange={(e) => {
                  const dt = { ...action.dataTransfer, confirmMessage: e.target.value };
                  updateActionConfig("dataTransfer", dt);
                }}
                placeholder="선택한 항목을 전달하시겠습니까?"
                className="h-7 text-xs"
              />
            </div>
          )}

          {commonMessageSection}
        </div>
      );

    case "event":
      return (
        <div className="rounded-lg border bg-muted/30 p-4 space-y-3">
          <div className="flex items-center gap-2">
            <Send className="h-4 w-4 text-primary" />
            <span className="text-sm font-medium">이벤트 설정</span>
          </div>
          <div>
            <Label className="text-xs">이벤트명</Label>
            <Input
              value={action.eventName || ""}
              onChange={(e) => updateActionConfig("eventName", e.target.value)}
              placeholder="이벤트 이름"
              className="h-7 text-xs"
            />
          </div>
          {commonMessageSection}
        </div>
      );

    default:
      return (
        <div className="rounded-lg border bg-muted/30 p-4 space-y-3">
          <div className="flex items-center gap-2">
            <Settings className="h-4 w-4 text-primary" />
            <span className="text-sm font-medium">기본 설정</span>
          </div>
          {commonMessageSection}
        </div>
      );
  }
};

// ─── 아이콘 설정 서브 컴포넌트 ───
const IconSettingsSection: React.FC<{
  actionType: string;
  isNoIconAction: boolean;
  currentActionIcons: string[];
  selectedIcon: string;
  selectedIconType: "lucide" | "svg";
  iconSize: string;
  displayMode: string;
  iconTextPosition: string;
  iconGap: number;
  customIcons: string[];
  customSvgIcons: Array<{ name: string; svg: string }>;
  lucideSearchOpen: boolean;
  setLucideSearchOpen: (open: boolean) => void;
  lucideSearchTerm: string;
  setLucideSearchTerm: (term: string) => void;
  svgPasteOpen: boolean;
  setSvgPasteOpen: (open: boolean) => void;
  svgInput: string;
  setSvgInput: (input: string) => void;
  svgName: string;
  setSvgName: (name: string) => void;
  svgError: string;
  setSvgError: (error: string) => void;
  onSelectIcon: (name: string, type?: "lucide" | "svg") => void;
  onRevertToDefault: () => void;
  onIconSizeChange: (preset: string) => void;
  onIconTextPositionChange: (pos: string) => void;
  onIconGapChange: (gap: number) => void;
  onCustomIconsChange: (icons: string[]) => void;
  onCustomSvgIconsChange: (icons: Array<{ name: string; svg: string }>) => void;
}> = ({
  actionType,
  isNoIconAction,
  currentActionIcons,
  selectedIcon,
  selectedIconType,
  iconSize,
  displayMode,
  iconTextPosition,
  iconGap,
  customIcons,
  customSvgIcons,
  lucideSearchOpen,
  setLucideSearchOpen,
  lucideSearchTerm,
  setLucideSearchTerm,
  svgPasteOpen,
  setSvgPasteOpen,
  svgInput,
  setSvgInput,
  svgName,
  setSvgName,
  svgError,
  setSvgError,
  onSelectIcon,
  onRevertToDefault,
  onIconSizeChange,
  onIconTextPositionChange,
  onIconGapChange,
  onCustomIconsChange,
  onCustomSvgIconsChange,
}) => {
  // 추천 아이콘 영역
  const renderIconGrid = (icons: string[], type: "lucide" | "svg" = "lucide") => (
    <div className="grid grid-cols-4 gap-1.5">
      {icons.map((iconName) => {
        const Icon = getLucideIcon(iconName);
        if (!Icon) return null;
        return (
          <button
            key={iconName}
            type="button"
            onClick={() => onSelectIcon(iconName, type)}
            className={cn(
              "hover:bg-muted flex flex-col items-center gap-1 rounded-md border p-2 transition-colors",
              selectedIcon === iconName && selectedIconType === type
                ? "border-primary ring-primary/30 bg-primary/5 ring-2"
                : "border-transparent"
            )}
          >
            <Icon className="h-5 w-5" />
            <span className="text-muted-foreground truncate text-[9px]">{iconName}</span>
          </button>
        );
      })}
    </div>
  );

  return (
    <div className="space-y-3">
      {/* 추천 아이콘 */}
      {isNoIconAction ? (
        <div className="text-muted-foreground rounded-md border border-dashed p-3 text-center text-xs">
          {NO_ICON_MESSAGE}
        </div>
      ) : (
        <div>
          <p className="mb-1.5 text-xs font-medium">추천 아이콘</p>
          {renderIconGrid(currentActionIcons)}
        </div>
      )}

      {/* 커스텀 아이콘 */}
      {(customIcons.length > 0 || customSvgIcons.length > 0) && (
        <>
          <div className="flex items-center gap-2">
            <div className="bg-border h-px flex-1" />
            <span className="text-muted-foreground text-[10px]">커스텀 아이콘</span>
            <div className="bg-border h-px flex-1" />
          </div>
          <div className="grid grid-cols-4 gap-1.5">
            {customIcons.map((iconName) => {
              const Icon = getLucideIcon(iconName);
              if (!Icon) return null;
              return (
                <div key={`custom-${iconName}`} className="relative">
                  <button
                    type="button"
                    onClick={() => onSelectIcon(iconName, "lucide")}
                    className={cn(
                      "hover:bg-muted flex w-full flex-col items-center gap-1 rounded-md border p-2 transition-colors",
                      selectedIcon === iconName && selectedIconType === "lucide"
                        ? "border-primary ring-primary/30 bg-primary/5 ring-2"
                        : "border-transparent"
                    )}
                  >
                    <Icon className="h-5 w-5" />
                    <span className="text-muted-foreground truncate text-[9px]">{iconName}</span>
                  </button>
                  <button
                    type="button"
                    onClick={() => {
                      onCustomIconsChange(customIcons.filter((n) => n !== iconName));
                      if (selectedIcon === iconName) onRevertToDefault();
                    }}
                    className="bg-destructive text-destructive-foreground hover:bg-destructive/80 absolute -top-1 -right-1 rounded-full p-0.5"
                  >
                    <X className="h-2.5 w-2.5" />
                  </button>
                </div>
              );
            })}
            {customSvgIcons.map((svgIcon) => (
              <div key={`svg-${svgIcon.name}`} className="relative">
                <button
                  type="button"
                  onClick={() => onSelectIcon(svgIcon.name, "svg")}
                  className={cn(
                    "hover:bg-muted flex w-full flex-col items-center gap-1 rounded-md border p-2 transition-colors",
                    selectedIcon === svgIcon.name && selectedIconType === "svg"
                      ? "border-primary ring-primary/30 bg-primary/5 ring-2"
                      : "border-transparent"
                  )}
                >
                  <span
                    className="flex h-5 w-5 items-center justify-center [&>svg]:h-full [&>svg]:w-full"
                    dangerouslySetInnerHTML={{ __html: sanitizeSvg(svgIcon.svg) }}
                  />
                  <span className="text-muted-foreground truncate text-[9px]">{svgIcon.name}</span>
                </button>
                <button
                  type="button"
                  onClick={() => {
                    onCustomSvgIconsChange(customSvgIcons.filter((s) => s.name !== svgIcon.name));
                    if (selectedIcon === svgIcon.name) onRevertToDefault();
                  }}
                  className="bg-destructive text-destructive-foreground hover:bg-destructive/80 absolute -top-1 -right-1 rounded-full p-0.5"
                >
                  <X className="h-2.5 w-2.5" />
                </button>
              </div>
            ))}
          </div>
        </>
      )}

      {/* 커스텀 아이콘 추가 */}
      <div className="flex gap-2">
        <Popover open={lucideSearchOpen} onOpenChange={setLucideSearchOpen}>
          <PopoverTrigger asChild>
            <Button variant="outline" size="sm" className="h-7 flex-1 text-xs">
              <Plus className="mr-1 h-3 w-3" />
              Lucide 검색
            </Button>
          </PopoverTrigger>
          <PopoverContent className="w-64 p-0" align="start">
            <Command>
              <CommandInput
                placeholder="아이콘 이름 검색..."
                value={lucideSearchTerm}
                onValueChange={setLucideSearchTerm}
                className="text-xs"
              />
              <CommandList className="max-h-48">
                <CommandEmpty className="py-3 text-xs">아이콘을 찾을 수 없습니다.</CommandEmpty>
                <CommandGroup>
                  {Object.keys(allLucideIcons)
                    .filter((name) => name.toLowerCase().includes(lucideSearchTerm.toLowerCase()))
                    .slice(0, 30)
                    .map((iconName) => {
                      const Icon = allLucideIcons[iconName as keyof typeof allLucideIcons];
                      return (
                        <CommandItem
                          key={iconName}
                          value={iconName}
                          onSelect={() => {
                            const next = [...customIcons];
                            if (!next.includes(iconName)) {
                              next.push(iconName);
                              onCustomIconsChange(next);
                              if (Icon) addToIconMap(iconName, Icon);
                            }
                            setLucideSearchOpen(false);
                            setLucideSearchTerm("");
                          }}
                          className="flex items-center gap-2 text-xs"
                        >
                          {Icon ? <Icon className="h-4 w-4" /> : <span className="h-4 w-4" />}
                          {iconName}
                          {customIcons.includes(iconName) && <Check className="text-primary ml-auto h-3 w-3" />}
                        </CommandItem>
                      );
                    })}
                </CommandGroup>
              </CommandList>
            </Command>
          </PopoverContent>
        </Popover>

        <Popover open={svgPasteOpen} onOpenChange={setSvgPasteOpen}>
          <PopoverTrigger asChild>
            <Button variant="outline" size="sm" className="h-7 flex-1 text-xs">
              <Plus className="mr-1 h-3 w-3" />
              SVG 붙여넣기
            </Button>
          </PopoverTrigger>
          <PopoverContent className="w-72 space-y-2 p-3" align="start">
            <Label className="text-xs">아이콘 이름</Label>
            <Input
              value={svgName}
              onChange={(e) => setSvgName(e.target.value)}
              placeholder="예: 회사로고"
              className="h-7 text-xs"
            />
            <Label className="text-xs">SVG 코드</Label>
            <textarea
              value={svgInput}
              onChange={(e) => {
                setSvgInput(e.target.value);
                setSvgError("");
              }}
              onPaste={(e) => {
                e.stopPropagation();
                const text = e.clipboardData.getData("text/plain");
                if (text) {
                  e.preventDefault();
                  setSvgInput(text);
                  setSvgError("");
                }
              }}
              onKeyDown={(e) => e.stopPropagation()}
              placeholder={'<svg xmlns="http://www.w3.org/2000/svg" ...>...</svg>'}
              className="bg-background focus:ring-ring h-20 w-full rounded-md border px-2 py-1.5 text-xs focus:ring-2 focus:outline-none"
            />
            {svgInput && (
              <div className="bg-muted/50 flex items-center justify-center rounded border p-2">
                <span
                  className="flex h-8 w-8 items-center justify-center [&>svg]:h-full [&>svg]:w-full"
                  dangerouslySetInnerHTML={{ __html: sanitizeSvg(svgInput) }}
                />
              </div>
            )}
            {svgError && <p className="text-destructive text-xs">{svgError}</p>}
            <Button
              size="sm"
              className="h-7 w-full text-xs"
              onClick={() => {
                if (!svgName.trim()) {
                  setSvgError("아이콘 이름을 입력하세요.");
                  return;
                }
                if (!svgInput.trim().includes("<svg")) {
                  setSvgError("유효한 SVG 코드가 아닙니다.");
                  return;
                }
                const sanitized = sanitizeSvg(svgInput);
                let finalName = svgName.trim();
                const existingNames = new Set(customSvgIcons.map((s) => s.name));
                if (existingNames.has(finalName)) {
                  let counter = 2;
                  while (existingNames.has(`${svgName.trim()}(${counter})`)) counter++;
                  finalName = `${svgName.trim()}(${counter})`;
                }
                onCustomSvgIconsChange([...customSvgIcons, { name: finalName, svg: sanitized }]);
                setSvgInput("");
                setSvgName("");
                setSvgError("");
                setSvgPasteOpen(false);
              }}
            >
              추가
            </Button>
          </PopoverContent>
        </Popover>
      </div>

      {/* 아이콘 크기 */}
      <div>
        <Label className="mb-1.5 text-xs">아이콘 크기</Label>
        <div className="flex rounded-md border">
          {Object.keys(iconSizePresets).map((preset) => (
            <button
              key={preset}
              type="button"
              onClick={() => onIconSizeChange(preset)}
              className={cn(
                "flex-1 px-1 py-1 text-xs font-medium whitespace-nowrap transition-colors first:rounded-l-md last:rounded-r-md",
                iconSize === preset
                  ? "bg-primary text-primary-foreground"
                  : "hover:bg-muted text-muted-foreground"
              )}
            >
              {preset}
            </button>
          ))}
        </div>
      </div>

      {/* 텍스트 위치 (icon-text 모드) */}
      {displayMode === "icon-text" && (
        <>
          <div>
            <Label className="mb-1.5 text-xs">텍스트 위치</Label>
            <div className="flex rounded-md border">
              {([
                { value: "left", label: "왼쪽" },
                { value: "right", label: "오른쪽" },
                { value: "top", label: "위쪽" },
                { value: "bottom", label: "아래쪽" },
              ] as const).map((pos) => (
                <button
                  key={pos.value}
                  type="button"
                  onClick={() => onIconTextPositionChange(pos.value)}
                  className={cn(
                    "flex-1 px-2 py-1 text-xs font-medium transition-colors first:rounded-l-md last:rounded-r-md",
                    iconTextPosition === pos.value
                      ? "bg-primary text-primary-foreground"
                      : "hover:bg-muted text-muted-foreground"
                  )}
                >
                  {pos.label}
                </button>
              ))}
            </div>
          </div>

          <div>
            <Label className="mb-1.5 text-xs">아이콘-텍스트 간격</Label>
            <div className="flex items-center gap-2">
              <input
                type="range"
                min={0}
                max={32}
                step={1}
                value={Math.min(iconGap, 32)}
                onChange={(e) => onIconGapChange(Number(e.target.value))}
                className="accent-primary h-1.5 flex-1 cursor-pointer"
              />
              <div className="flex items-center gap-1">
                <Input
                  type="number"
                  min={0}
                  value={iconGap}
                  onChange={(e) => onIconGapChange(Math.max(0, Number(e.target.value) || 0))}
                  className="h-7 w-14 text-center text-xs"
                />
                <span className="text-muted-foreground text-xs">px</span>
              </div>
            </div>
          </div>
        </>
      )}
    </div>
  );
};

// ─── 데이터 전달 필드 매핑 서브 컴포넌트 (고급 설정 내부) ───
const TransferDataFieldMappingSection: React.FC<{
  config: Record<string, any>;
  onChange: (config: Record<string, any>) => void;
  availableTables: Array<{ name: string; label: string }>;
  mappingSourceColumnsMap: Record<string, Array<{ name: string; label: string }>>;
  setMappingSourceColumnsMap: React.Dispatch<React.SetStateAction<Record<string, Array<{ name: string; label: string }>>>>;
  mappingTargetColumns: Array<{ name: string; label: string }>;
  fieldMappingOpen: boolean;
  setFieldMappingOpen: (open: boolean) => void;
  activeMappingGroupIndex: number;
  setActiveMappingGroupIndex: (index: number) => void;
  loadTableColumns: (tableName: string) => Promise<Array<{ name: string; label: string }>>;
}> = ({
  config,
  onChange,
  availableTables,
  mappingSourceColumnsMap,
  setMappingSourceColumnsMap,
  mappingTargetColumns,
  activeMappingGroupIndex,
  setActiveMappingGroupIndex,
  loadTableColumns,
}) => {
  const [sourcePopoverOpen, setSourcePopoverOpen] = useState<Record<string, boolean>>({});
  const [targetPopoverOpen, setTargetPopoverOpen] = useState<Record<string, boolean>>({});

  const dataTransfer = config.action?.dataTransfer || {};
  const multiTableMappings: Array<{ sourceTable: string; mappingRules: Array<{ sourceField: string; targetField: string }> }> =
    dataTransfer.multiTableMappings || [];

  const updateDataTransfer = (field: string, value: any) => {
    const currentAction = config.action || {};
    const currentDt = currentAction.dataTransfer || {};
    onChange({
      ...config,
      action: {
        ...currentAction,
        dataTransfer: { ...currentDt, [field]: value },
      },
    });
  };

  const activeGroup = multiTableMappings[activeMappingGroupIndex];
  const activeSourceTable = activeGroup?.sourceTable || "";
  const activeSourceColumns = mappingSourceColumnsMap[activeSourceTable] || [];
  const activeRules = activeGroup?.mappingRules || [];

  const updateGroupField = (field: string, value: any) => {
    const mappings = [...multiTableMappings];
    mappings[activeMappingGroupIndex] = { ...mappings[activeMappingGroupIndex], [field]: value };
    updateDataTransfer("multiTableMappings", mappings);
  };

  return (
    <div className="space-y-3">
      <div className="space-y-0.5">
        <p className="text-sm font-medium">필드 매핑</p>
        <p className="text-[11px] text-muted-foreground">
          레이어별로 소스 테이블이 다를 때 각각 매핑 규칙을 설정해요
        </p>
      </div>

      {/* 타겟 테이블 (공통) */}
      <div>
        <Label className="text-xs">타겟 테이블 (공통)</Label>
        <Popover>
          <PopoverTrigger asChild>
            <Button variant="outline" role="combobox" className="h-8 w-full justify-between text-xs">
              {dataTransfer.targetTable
                ? availableTables.find((t) => t.name === dataTransfer.targetTable)?.label ||
                  dataTransfer.targetTable
                : "타겟 테이블 선택"}
              <ChevronsUpDown className="ml-2 h-3 w-3 shrink-0 opacity-50" />
            </Button>
          </PopoverTrigger>
          <PopoverContent className="p-0" style={{ width: "var(--radix-popover-trigger-width)" }} align="start">
            <Command>
              <CommandInput placeholder="테이블 검색..." className="text-xs" />
              <CommandList className="max-h-48">
                <CommandEmpty className="py-3 text-xs">테이블을 찾을 수 없습니다</CommandEmpty>
                <CommandGroup>
                  {availableTables.map((table) => (
                    <CommandItem
                      key={table.name}
                      value={`${table.label} ${table.name}`}
                      onSelect={() => updateDataTransfer("targetTable", table.name)}
                      className="text-xs"
                    >
                      <Check className={cn("mr-2 h-3 w-3", dataTransfer.targetTable === table.name ? "opacity-100" : "opacity-0")} />
                      <div className="flex flex-col">
                        <span className="font-medium">{table.label}</span>
                        {table.label !== table.name && <span className="text-[10px] text-muted-foreground">{table.name}</span>}
                      </div>
                    </CommandItem>
                  ))}
                </CommandGroup>
              </CommandList>
            </Command>
          </PopoverContent>
        </Popover>
      </div>

      {/* 소스 테이블 그룹 탭 + 추가 버튼 */}
      <div className="space-y-2">
        <div className="flex items-center justify-between">
          <Label className="text-xs">소스 테이블별 매핑</Label>
          <Button
            type="button"
            variant="outline"
            size="sm"
            className="h-7 text-xs"
            onClick={() => {
              updateDataTransfer("multiTableMappings", [
                ...multiTableMappings,
                { sourceTable: "", mappingRules: [] },
              ]);
              setActiveMappingGroupIndex(multiTableMappings.length);
            }}
            disabled={!dataTransfer.targetTable}
          >
            <Plus className="mr-1 h-3.5 w-3.5" />
            소스 테이블 추가
          </Button>
        </div>

        {!dataTransfer.targetTable ? (
          <div className="rounded-lg border border-dashed p-4 text-center">
            <p className="text-xs text-muted-foreground">타겟 테이블을 먼저 선택하세요</p>
          </div>
        ) : multiTableMappings.length === 0 ? (
          <div className="rounded-lg border border-dashed p-4 text-center">
            <p className="text-xs text-muted-foreground">소스 테이블을 추가하세요</p>
          </div>
        ) : (
          <div className="space-y-3">
            {/* 그룹 탭 */}
            <div className="flex flex-wrap gap-1.5">
              {multiTableMappings.map((group, gIdx) => (
                <div key={gIdx} className="flex items-center">
                  <Button
                    type="button"
                    variant={activeMappingGroupIndex === gIdx ? "default" : "outline"}
                    size="sm"
                    className="h-7 text-xs rounded-r-none"
                    onClick={() => setActiveMappingGroupIndex(gIdx)}
                  >
                    {group.sourceTable
                      ? availableTables.find((t) => t.name === group.sourceTable)?.label || group.sourceTable
                      : `그룹 ${gIdx + 1}`}
                    {group.mappingRules?.length > 0 && (
                      <span className="ml-1.5 rounded-full bg-primary-foreground/20 px-1.5 text-[10px]">
                        {group.mappingRules.length}
                      </span>
                    )}
                  </Button>
                  <Button
                    type="button"
                    variant={activeMappingGroupIndex === gIdx ? "default" : "outline"}
                    size="icon"
                    className="h-7 w-7 rounded-l-none border-l-0"
                    onClick={() => {
                      const mappings = [...multiTableMappings];
                      mappings.splice(gIdx, 1);
                      updateDataTransfer("multiTableMappings", mappings);
                      if (activeMappingGroupIndex >= mappings.length) {
                        setActiveMappingGroupIndex(Math.max(0, mappings.length - 1));
                      }
                    }}
                  >
                    <X className="h-3 w-3" />
                  </Button>
                </div>
              ))}
            </div>

            {/* 활성 그룹 편집 */}
            {activeGroup && (
              <div className="space-y-3 rounded-lg border p-3">
                {/* 소스 테이블 선택 */}
                <div>
                  <Label className="text-xs">소스 테이블</Label>
                  <Popover>
                    <PopoverTrigger asChild>
                      <Button variant="outline" role="combobox" className="h-8 w-full justify-between text-xs">
                        {activeSourceTable
                          ? availableTables.find((t) => t.name === activeSourceTable)?.label || activeSourceTable
                          : "소스 테이블 선택"}
                        <ChevronsUpDown className="ml-2 h-3 w-3 shrink-0 opacity-50" />
                      </Button>
                    </PopoverTrigger>
                    <PopoverContent className="p-0" style={{ width: "var(--radix-popover-trigger-width)" }} align="start">
                      <Command>
                        <CommandInput placeholder="테이블 검색..." className="text-xs" />
                        <CommandList className="max-h-48">
                          <CommandEmpty className="py-3 text-xs">테이블을 찾을 수 없습니다</CommandEmpty>
                          <CommandGroup>
                            {availableTables.map((table) => (
                              <CommandItem
                                key={table.name}
                                value={`${table.label} ${table.name}`}
                                onSelect={async () => {
                                  updateGroupField("sourceTable", table.name);
                                  if (!mappingSourceColumnsMap[table.name]) {
                                    const cols = await loadTableColumns(table.name);
                                    setMappingSourceColumnsMap((prev) => ({ ...prev, [table.name]: cols }));
                                  }
                                }}
                                className="text-xs"
                              >
                                <Check className={cn("mr-2 h-3 w-3", activeSourceTable === table.name ? "opacity-100" : "opacity-0")} />
                                <div className="flex flex-col">
                                  <span className="font-medium">{table.label}</span>
                                  {table.label !== table.name && <span className="text-[10px] text-muted-foreground">{table.name}</span>}
                                </div>
                              </CommandItem>
                            ))}
                          </CommandGroup>
                        </CommandList>
                      </Command>
                    </PopoverContent>
                  </Popover>
                </div>

                {/* 매핑 규칙 */}
                <div className="space-y-2">
                  <div className="flex items-center justify-between">
                    <Label className="text-xs">매핑 규칙</Label>
                    <Button
                      type="button"
                      variant="outline"
                      size="sm"
                      className="h-7 text-xs"
                      onClick={() => {
                        updateGroupField("mappingRules", [
                          ...activeRules,
                          { sourceField: "", targetField: "" },
                        ]);
                      }}
                      disabled={!activeSourceTable}
                    >
                      <Plus className="mr-1 h-3.5 w-3.5" />
                      추가
                    </Button>
                  </div>

                  {!activeSourceTable ? (
                    <p className="text-xs text-muted-foreground">소스 테이블을 먼저 선택하세요</p>
                  ) : activeRules.length === 0 ? (
                    <p className="text-xs text-muted-foreground">매핑 없음 (동일 필드명 자동 매핑)</p>
                  ) : (
                    <div className="space-y-2">
                      {activeRules.map((rule: any, rIdx: number) => {
                        const keyS = `${activeMappingGroupIndex}-${rIdx}-s`;
                        const keyT = `${activeMappingGroupIndex}-${rIdx}-t`;
                        return (
                          <div
                            key={rIdx}
                            className="grid items-center gap-1.5"
                            style={{ gridTemplateColumns: "1fr 16px 1fr 32px" }}
                          >
                            {/* 소스 필드 */}
                            <Popover
                              open={sourcePopoverOpen[keyS] || false}
                              onOpenChange={(open) => setSourcePopoverOpen((prev) => ({ ...prev, [keyS]: open }))}
                            >
                              <PopoverTrigger asChild>
                                <Button variant="outline" role="combobox" className="h-8 w-full justify-between text-xs overflow-hidden">
                                  <span className="truncate">
                                    {rule.sourceField
                                      ? activeSourceColumns.find((c) => c.name === rule.sourceField)?.label || rule.sourceField
                                      : "소스 컬럼"}
                                  </span>
                                  <ChevronsUpDown className="ml-1 h-3 w-3 shrink-0 opacity-50" />
                                </Button>
                              </PopoverTrigger>
                              <PopoverContent className="w-[220px] p-0" align="start">
                                <Command>
                                  <CommandInput placeholder="컬럼 검색..." className="text-xs" />
                                  <CommandList className="max-h-48">
                                    <CommandEmpty className="py-3 text-xs">찾을 수 없습니다</CommandEmpty>
                                    <CommandGroup>
                                      {activeSourceColumns.map((col) => (
                                        <CommandItem
                                          key={col.name}
                                          value={`${col.label} ${col.name}`}
                                          onSelect={() => {
                                            const newRules = [...activeRules];
                                            newRules[rIdx] = { ...newRules[rIdx], sourceField: col.name };
                                            updateGroupField("mappingRules", newRules);
                                            setSourcePopoverOpen((prev) => ({ ...prev, [keyS]: false }));
                                          }}
                                          className="text-xs"
                                        >
                                          <Check className={cn("mr-2 h-3 w-3", rule.sourceField === col.name ? "opacity-100" : "opacity-0")} />
                                          <span className="font-medium">{col.label}</span>
                                          {col.label !== col.name && <span className="ml-1 text-muted-foreground">({col.name})</span>}
                                        </CommandItem>
                                      ))}
                                    </CommandGroup>
                                  </CommandList>
                                </Command>
                              </PopoverContent>
                            </Popover>

                            <ArrowRight className="mx-auto h-4 w-4 text-muted-foreground" />

                            {/* 타겟 필드 */}
                            <Popover
                              open={targetPopoverOpen[keyT] || false}
                              onOpenChange={(open) => setTargetPopoverOpen((prev) => ({ ...prev, [keyT]: open }))}
                            >
                              <PopoverTrigger asChild>
                                <Button variant="outline" role="combobox" className="h-8 w-full justify-between text-xs overflow-hidden">
                                  <span className="truncate">
                                    {rule.targetField
                                      ? mappingTargetColumns.find((c) => c.name === rule.targetField)?.label || rule.targetField
                                      : "타겟 컬럼"}
                                  </span>
                                  <ChevronsUpDown className="ml-1 h-3 w-3 shrink-0 opacity-50" />
                                </Button>
                              </PopoverTrigger>
                              <PopoverContent className="w-[220px] p-0" align="start">
                                <Command>
                                  <CommandInput placeholder="컬럼 검색..." className="text-xs" />
                                  <CommandList className="max-h-48">
                                    <CommandEmpty className="py-3 text-xs">찾을 수 없습니다</CommandEmpty>
                                    <CommandGroup>
                                      {mappingTargetColumns.map((col) => (
                                        <CommandItem
                                          key={col.name}
                                          value={`${col.label} ${col.name}`}
                                          onSelect={() => {
                                            const newRules = [...activeRules];
                                            newRules[rIdx] = { ...newRules[rIdx], targetField: col.name };
                                            updateGroupField("mappingRules", newRules);
                                            setTargetPopoverOpen((prev) => ({ ...prev, [keyT]: false }));
                                          }}
                                          className="text-xs"
                                        >
                                          <Check className={cn("mr-2 h-3 w-3", rule.targetField === col.name ? "opacity-100" : "opacity-0")} />
                                          <span className="font-medium">{col.label}</span>
                                          {col.label !== col.name && <span className="ml-1 text-muted-foreground">({col.name})</span>}
                                        </CommandItem>
                                      ))}
                                    </CommandGroup>
                                  </CommandList>
                                </Command>
                              </PopoverContent>
                            </Popover>

                            {/* 삭제 */}
                            <Button
                              type="button"
                              variant="ghost"
                              size="icon"
                              className="h-8 w-8 text-destructive hover:bg-destructive/10"
                              onClick={() => {
                                const newRules = [...activeRules];
                                newRules.splice(rIdx, 1);
                                updateGroupField("mappingRules", newRules);
                              }}
                            >
                              <X className="h-4 w-4" />
                            </Button>
                          </div>
                        );
                      })}
                    </div>
                  )}
                </div>
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  );
};

V2ButtonConfigPanel.displayName = "V2ButtonConfigPanel";

export default V2ButtonConfigPanel;
