"use client";

import React, { useState, useEffect, useCallback, useMemo } from "react";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";
import { Plus, X, GripVertical, Check, ChevronsUpDown, Table, Layers, ChevronUp, ChevronDown } from "lucide-react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Badge } from "@/components/ui/badge";
import {
  RepeatScreenModalProps,
  CardRowConfig,
  CardColumnConfig,
  ColumnSourceConfig,
  ColumnTargetConfig,
  GroupingConfig,
  AggregationConfig,
  TableLayoutConfig,
  TableColumnConfig,
  CardContentRowConfig,
  AggregationDisplayConfig,
  SyncSaveConfig,
  RowNumberingConfig,
} from "./types";
import { tableManagementApi } from "@/lib/api/tableManagement";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { cn } from "@/lib/utils";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog";
import { ScrollArea } from "@/components/ui/scroll-area";

interface RepeatScreenModalConfigPanelProps {
  config: Partial<RepeatScreenModalProps>;
  onChange: (config: Partial<RepeatScreenModalProps>) => void;
}

// 검색 가능한 컬럼 선택기 (Combobox) - 240px 최적화
function SourceColumnSelector({
  sourceTable,
  value,
  onChange,
  placeholder = "컬럼 선택",
}: {
  sourceTable: string;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  showTableName?: boolean;
}) {
  const [columns, setColumns] = useState<{ columnName: string; displayName?: string }[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [open, setOpen] = useState(false);

  useEffect(() => {
    const loadColumns = async () => {
      if (!sourceTable) {
        setColumns([]);
        return;
      }

      setIsLoading(true);
      try {
        const response = await tableManagementApi.getColumnList(sourceTable);
        if (response.success && response.data) {
          setColumns(response.data.columns);
        }
      } catch (error) {
        console.error("컬럼 로드 실패:", error);
        setColumns([]);
      } finally {
        setIsLoading(false);
      }
    };
    loadColumns();
  }, [sourceTable]);

  const selectedColumn = columns.find((col) => col.columnName === value);
  const displayText = selectedColumn ? selectedColumn.columnName : placeholder;

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          variant="outline"
          role="combobox"
          aria-expanded={open}
          className="h-6 w-full justify-between text-[10px] min-w-0 shrink"
          disabled={!sourceTable || isLoading}
        >
          <span className="truncate">{isLoading ? "..." : displayText}</span>
          <ChevronsUpDown className="ml-1 h-3 w-3 shrink-0 opacity-50" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="p-0 max-h-[200px]" style={{ width: "var(--radix-popover-trigger-width)" }} align="start">
        <Command>
          <CommandInput placeholder="검색..." className="text-[10px] h-7" />
          <CommandList className="max-h-[160px] overflow-y-auto">
            <CommandEmpty className="text-[10px] py-2">없음</CommandEmpty>
            <CommandGroup>
              {columns.map((col) => (
                <CommandItem
                  key={col.columnName}
                  value={`${col.columnName} ${col.displayName || ""}`}
                  onSelect={() => {
                    onChange(col.columnName);
                    setOpen(false);
                  }}
                  className="text-[10px] py-1"
                >
                  <Check
                    className={cn("mr-1 h-3 w-3", value === col.columnName ? "opacity-100" : "opacity-0")}
                  />
                  <span className="truncate">{col.columnName}</span>
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  );
}

// 카드 제목 편집기 - 직접 입력 + 필드 삽입 방식
function CardTitleEditor({
  sourceTable,
  currentValue,
  onChange,
}: {
  sourceTable: string;
  currentValue: string;
  onChange: (value: string) => void;
}) {
  const [columns, setColumns] = useState<{ columnName: string; displayName?: string }[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [open, setOpen] = useState(false);
  const [localValue, setLocalValue] = useState(currentValue || "");
  const inputRef = React.useRef<HTMLInputElement>(null);

  useEffect(() => {
    setLocalValue(currentValue || "");
  }, [currentValue]);

  useEffect(() => {
    const loadColumns = async () => {
      if (!sourceTable) {
        setColumns([]);
        return;
      }

      setIsLoading(true);
      try {
        const response = await tableManagementApi.getColumnList(sourceTable);
        if (response.success && response.data) {
          setColumns(response.data.columns || []);
        }
      } catch (error) {
        console.error("컬럼 로드 실패:", error);
        setColumns([]);
      } finally {
        setIsLoading(false);
      }
    };
    loadColumns();
  }, [sourceTable]);

  // 필드 삽입 (현재 커서 위치 또는 끝에)
  const insertField = (fieldName: string) => {
    const newValue = localValue ? `${localValue} - {${fieldName}}` : `{${fieldName}}`;
    setLocalValue(newValue);
    onChange(newValue);
    setOpen(false);
  };

  // 추천 템플릿
  const templateOptions = useMemo(() => {
    const options = [
      { value: "카드 {index}", label: "카드 {index} - 순번만" },
    ];

    if (columns.length > 0) {
      // part_code - part_name 패턴 찾기
      const codeCol = columns.find((c) => 
        c.columnName.toLowerCase().includes("code") || c.columnName.toLowerCase().includes("no")
      );
      const nameCol = columns.find((c) => 
        c.columnName.toLowerCase().includes("name") && !c.columnName.toLowerCase().includes("code")
      );

      if (codeCol && nameCol) {
        options.push({
          value: `{${codeCol.columnName}} - {${nameCol.columnName}}`,
          label: `{${codeCol.columnName}} - {${nameCol.columnName}} (추천)`,
        });
      }

      // 첫 번째 컬럼 단일
      const firstCol = columns[0];
      options.push({
        value: `{${firstCol.columnName}}`,
        label: `{${firstCol.columnName}}${firstCol.displayName ? ` - ${firstCol.displayName}` : ""}`,
      });
    }

    return options;
  }, [columns]);

  // 입력값 변경 핸들러
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setLocalValue(e.target.value);
  };

  // 입력 완료 (blur 또는 Enter)
  const handleInputBlur = () => {
    if (localValue !== currentValue) {
      onChange(localValue);
    }
  };

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (e.key === "Enter") {
      handleInputBlur();
    }
  };

  return (
    <div className="space-y-1.5">
      {/* 직접 입력 필드 */}
      <div className="flex gap-1">
        <Input
          ref={inputRef}
          value={localValue}
          onChange={handleInputChange}
          onBlur={handleInputBlur}
          onKeyDown={handleKeyDown}
          placeholder="{part_code} - {part_name}"
          className="h-7 text-[10px] flex-1"
        />
        <Popover open={open} onOpenChange={setOpen}>
          <PopoverTrigger asChild>
            <Button
              variant="outline"
              size="sm"
              className="h-7 px-2 text-[9px]"
              disabled={isLoading || !sourceTable}
            >
              <Plus className="h-3 w-3" />
            </Button>
          </PopoverTrigger>
          <PopoverContent className="p-0 w-[200px]" align="end">
            <Command>
              <CommandInput placeholder="필드 검색..." className="text-[10px] h-7" />
              <CommandList className="max-h-[200px] overflow-y-auto">
                <CommandEmpty className="text-[10px] py-2 text-center">없음</CommandEmpty>
                
                {/* 추천 템플릿 */}
                <CommandGroup heading="추천 템플릿">
                  {templateOptions.map((opt) => (
                    <CommandItem
                      key={opt.value}
                      value={opt.value}
                      onSelect={() => {
                        setLocalValue(opt.value);
                        onChange(opt.value);
                        setOpen(false);
                      }}
                      className="text-[10px] py-1"
                    >
                      <span className="truncate">{opt.label}</span>
                    </CommandItem>
                  ))}
                </CommandGroup>

                {/* 필드 삽입 */}
                {columns.length > 0 && (
                  <CommandGroup heading="필드 추가 (끝에 삽입)">
                    <CommandItem
                      key="_index"
                      value="index"
                      onSelect={() => insertField("index")}
                      className="text-[10px] py-1"
                    >
                      <Plus className="h-3 w-3 mr-1 text-primary" />
                      <span>index - 순번</span>
                    </CommandItem>
                    {columns.map((col) => (
                      <CommandItem
                        key={col.columnName}
                        value={col.columnName}
                        onSelect={() => insertField(col.columnName)}
                        className="text-[10px] py-1"
                      >
                        <Plus className="h-3 w-3 mr-1 text-primary" />
                        <span className="truncate">
                          {col.columnName}
                          {col.displayName && (
                            <span className="text-muted-foreground ml-1">- {col.displayName}</span>
                          )}
                        </span>
                      </CommandItem>
                    ))}
                  </CommandGroup>
                )}
              </CommandList>
            </Command>
          </PopoverContent>
        </Popover>
      </div>

      {/* 안내 텍스트 */}
      <p className="text-[9px] text-muted-foreground">
        직접 입력하거나 + 버튼으로 필드 추가. 예: {"{part_code} - {part_name}"}
      </p>
    </div>
  );
}

// 🆕 v3.2: 시각적 수식 빌더
interface FormulaToken {
  id: string;
  type: "aggregation" | "column" | "operator" | "number";
  // aggregation: 이전 집계 결과 참조
  aggregationField?: string;
  // column: 테이블 컬럼 집계
  table?: string;
  column?: string;
  aggFunction?: "SUM" | "COUNT" | "AVG" | "MIN" | "MAX" | "SUM_EXT" | "COUNT_EXT" | "AVG_EXT" | "MIN_EXT" | "MAX_EXT" | "VALUE";
  isExternal?: boolean;
  // operator: 연산자
  operator?: "+" | "-" | "*" | "/" | "(" | ")";
  // number: 숫자
  value?: number;
}

function FormulaBuilder({
  formula,
  sourceTable,
  allTables,
  referenceableAggregations,
  onChange,
}: {
  formula: string;
  sourceTable: string;
  allTables: { tableName: string; displayName?: string }[];
  referenceableAggregations: AggregationConfig[];
  onChange: (formula: string) => void;
}) {
  // 수식 토큰 상태
  const [tokens, setTokens] = useState<FormulaToken[]>([]);
  
  // 새 토큰 추가용 상태
  const [newTokenType, setNewTokenType] = useState<"aggregation" | "column">("aggregation");
  const [newTokenTable, setNewTokenTable] = useState(sourceTable || "");
  const [newTokenColumn, setNewTokenColumn] = useState("");
  const [newTokenAggFunction, setNewTokenAggFunction] = useState<FormulaToken["aggFunction"]>("SUM");
  const [newTokenAggField, setNewTokenAggField] = useState("");

  // formula 문자열에서 토큰 파싱 (초기화용)
  useEffect(() => {
    if (!formula) {
      setTokens([]);
      return;
    }
    
    // 간단한 파싱: 기존 formula가 있으면 토큰으로 변환 시도
    const parsed = parseFormulaToTokens(formula, sourceTable);
    if (parsed.length > 0) {
      setTokens(parsed);
    }
  }, []);

  // 토큰을 formula 문자열로 변환
  const tokensToFormula = (tokenList: FormulaToken[]): string => {
    return tokenList.map((token) => {
      switch (token.type) {
        case "aggregation":
          return `{${token.aggregationField}}`;
        case "column":
          if (token.aggFunction === "VALUE") {
            return `{${token.column}}`;
          }
          return `${token.aggFunction}({${token.column}})`;
        case "operator":
          return ` ${token.operator} `;
        case "number":
          return String(token.value);
        default:
          return "";
      }
    }).join("");
  };

  // formula 문자열에서 토큰 파싱 (간단한 버전)
  const parseFormulaToTokens = (formulaStr: string, defaultTable: string): FormulaToken[] => {
    const result: FormulaToken[] = [];
    // 간단한 파싱 - 복잡한 경우는 수동 입력 모드로 전환
    // 이 함수는 기존 formula가 있을 때 최대한 파싱 시도
    const parts = formulaStr.split(/(\s*[+\-*/()]\s*)/);
    
    for (const part of parts) {
      const trimmed = part.trim();
      if (!trimmed) continue;
      
      // 연산자
      if (["+", "-", "*", "/", "(", ")"].includes(trimmed)) {
        result.push({
          id: `op-${Date.now()}-${Math.random()}`,
          type: "operator",
          operator: trimmed as FormulaToken["operator"],
        });
        continue;
      }
      
      // 집계 함수: SUM({column}), SUM_EXT({column})
      const aggMatch = trimmed.match(/^(SUM|COUNT|AVG|MIN|MAX)(_EXT)?\(\{(\w+)\}\)$/);
      if (aggMatch) {
        result.push({
          id: `col-${Date.now()}-${Math.random()}`,
          type: "column",
          table: aggMatch[2] ? "" : defaultTable, // _EXT면 외부 테이블
          column: aggMatch[3],
          aggFunction: (aggMatch[1] + (aggMatch[2] || "")) as FormulaToken["aggFunction"],
          isExternal: !!aggMatch[2],
        });
        continue;
      }
      
      // 필드 참조: {fieldName}
      const fieldMatch = trimmed.match(/^\{(\w+)\}$/);
      if (fieldMatch) {
        result.push({
          id: `agg-${Date.now()}-${Math.random()}`,
          type: "aggregation",
          aggregationField: fieldMatch[1],
        });
        continue;
      }
      
      // 숫자
      const num = parseFloat(trimmed);
      if (!isNaN(num)) {
        result.push({
          id: `num-${Date.now()}-${Math.random()}`,
          type: "number",
          value: num,
        });
      }
    }
    
    return result;
  };

  // 토큰 추가
  const addToken = (token: FormulaToken) => {
    const newTokens = [...tokens, token];
    setTokens(newTokens);
    onChange(tokensToFormula(newTokens));
  };

  // 토큰 삭제
  const removeToken = (tokenId: string) => {
    const newTokens = tokens.filter((t) => t.id !== tokenId);
    setTokens(newTokens);
    onChange(tokensToFormula(newTokens));
  };

  // 연산자 추가
  const addOperator = (op: FormulaToken["operator"]) => {
    addToken({
      id: `op-${Date.now()}`,
      type: "operator",
      operator: op,
    });
  };

  // 집계 참조 추가
  const addAggregationRef = () => {
    if (!newTokenAggField) return;
    addToken({
      id: `agg-${Date.now()}`,
      type: "aggregation",
      aggregationField: newTokenAggField,
    });
    setNewTokenAggField("");
  };

  // 컬럼 집계 추가
  const addColumnAgg = () => {
    if (!newTokenColumn) return;
    const isExternal = newTokenTable !== sourceTable;
    let aggFunc = newTokenAggFunction;
    
    // 외부 테이블이면 _EXT 붙이기
    if (isExternal && aggFunc && !aggFunc.endsWith("_EXT") && aggFunc !== "VALUE") {
      aggFunc = (aggFunc + "_EXT") as FormulaToken["aggFunction"];
    }
    
    addToken({
      id: `col-${Date.now()}`,
      type: "column",
      table: newTokenTable,
      column: newTokenColumn,
      aggFunction: aggFunc,
      isExternal,
    });
    setNewTokenColumn("");
  };

  // 토큰 표시 텍스트
  const getTokenDisplay = (token: FormulaToken): string => {
    switch (token.type) {
      case "aggregation":
        const refAgg = referenceableAggregations.find((a) => a.resultField === token.aggregationField);
        return refAgg?.label || token.aggregationField || "";
      case "column":
        if (token.aggFunction === "VALUE") {
          return `${token.column}`;
        }
        return `${token.aggFunction}(${token.column})`;
      case "operator":
        return token.operator || "";
      case "number":
        return String(token.value);
      default:
        return "";
    }
  };

  // 토큰 배지 색상
  const getTokenBadgeClass = (token: FormulaToken): string => {
    switch (token.type) {
      case "aggregation":
        return "bg-blue-100 text-blue-700 border-blue-200";
      case "column":
        return token.isExternal 
          ? "bg-orange-100 text-orange-700 border-orange-200" 
          : "bg-green-100 text-green-700 border-green-200";
      case "operator":
        return "bg-gray-100 text-gray-700 border-gray-200";
      case "number":
        return "bg-purple-100 text-purple-700 border-purple-200";
      default:
        return "";
    }
  };

  return (
    <div className="space-y-2 overflow-hidden min-w-0">
      {/* 현재 수식 표시 */}
      <div className="space-y-1 min-w-0">
        <Label className="text-[9px]">수식</Label>
        <div className="min-h-[32px] p-1.5 bg-muted/50 rounded border border-dashed flex flex-wrap gap-1 items-center overflow-hidden">
          {tokens.length === 0 ? (
            <span className="text-[9px] text-muted-foreground">아래에서 요소를 추가하세요</span>
          ) : (
            tokens.map((token) => (
              <Badge
                key={token.id}
                variant="outline"
                className={cn(
                  "text-[9px] px-1.5 py-0.5 cursor-pointer hover:opacity-70 flex items-center gap-0.5",
                  getTokenBadgeClass(token)
                )}
                onClick={() => removeToken(token.id)}
                title="클릭하여 삭제"
              >
                {getTokenDisplay(token)}
                <X className="h-2 w-2" />
              </Badge>
            ))
          )}
        </div>
        {/* 생성된 수식 미리보기 */}
        {tokens.length > 0 && (
          <p className="text-[8px] font-mono text-muted-foreground bg-muted/30 px-1.5 py-0.5 rounded">
            {tokensToFormula(tokens)}
          </p>
        )}
      </div>

      {/* 연산자 버튼 */}
      <div className="space-y-1">
        <Label className="text-[9px]">연산자</Label>
        <div className="flex gap-1">
          {["+", "-", "*", "/", "(", ")"].map((op) => (
            <Button
              key={op}
              size="sm"
              variant="outline"
              onClick={() => addOperator(op as FormulaToken["operator"])}
              className="h-6 w-6 p-0 text-[10px] font-mono"
            >
              {op}
            </Button>
          ))}
        </div>
      </div>

      {/* 집계 참조 추가 */}
      {referenceableAggregations.length > 0 && (
        <div className="space-y-2 p-2 bg-blue-50 dark:bg-blue-950 rounded border border-blue-200 dark:border-blue-800 overflow-hidden min-w-0">
          <Label className="text-[9px] text-blue-700 dark:text-blue-300">이전 집계 참조</Label>
          <div className="space-y-1">
            <span className="text-[8px] text-muted-foreground">참조할 집계 선택</span>
            <div className="flex gap-1">
              <Select value={newTokenAggField} onValueChange={setNewTokenAggField}>
                <SelectTrigger className="h-6 text-[10px] flex-1">
                  <SelectValue placeholder="집계 선택" />
                </SelectTrigger>
                <SelectContent>
                  {referenceableAggregations.map((agg) => (
                    <SelectItem key={agg.resultField} value={agg.resultField} className="text-[10px]">
                      {agg.label || agg.resultField}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <Button
                size="sm"
                variant="outline"
                onClick={addAggregationRef}
                disabled={!newTokenAggField}
                className="h-6 text-[9px] px-3 shrink-0"
              >
                <Plus className="h-3 w-3 mr-1" />
                추가
              </Button>
            </div>
          </div>
        </div>
      )}

      {/* 테이블 컬럼 집계 추가 */}
      <div className="space-y-2 p-2 bg-green-50 dark:bg-green-950 rounded border border-green-200 dark:border-green-800 overflow-hidden min-w-0">
        <Label className="text-[9px] text-green-700 dark:text-green-300">테이블 컬럼 집계</Label>
        
        {/* 테이블 선택 */}
        <div className="space-y-1">
          <span className="text-[8px] text-muted-foreground">테이블</span>
          <Select value={newTokenTable} onValueChange={(v) => { setNewTokenTable(v); setNewTokenColumn(""); }}>
            <SelectTrigger className="h-6 text-[10px] w-full">
              <SelectValue placeholder="테이블 선택" />
            </SelectTrigger>
            <SelectContent>
              {sourceTable && (
                <SelectItem value={sourceTable} className="text-[10px]">
                  {sourceTable} (기본)
                </SelectItem>
              )}
              {allTables
                .filter((t) => t.tableName !== sourceTable)
                .map((t) => (
                  <SelectItem key={t.tableName} value={t.tableName} className="text-[10px]">
                    {t.displayName || t.tableName} (외부)
                  </SelectItem>
                ))}
            </SelectContent>
          </Select>
        </div>

        {/* 컬럼 선택 */}
        <div className="space-y-1">
          <span className="text-[8px] text-muted-foreground">컬럼</span>
          <SourceColumnSelector
            sourceTable={newTokenTable}
            value={newTokenColumn}
            onChange={setNewTokenColumn}
            placeholder="컬럼 선택"
          />
        </div>

        {/* 집계 함수 및 추가 버튼 */}
        <div className="flex gap-1">
          <div className="flex-1 space-y-1">
            <span className="text-[8px] text-muted-foreground">집계 함수</span>
            <Select value={newTokenAggFunction} onValueChange={(v) => setNewTokenAggFunction(v as FormulaToken["aggFunction"])}>
              <SelectTrigger className="h-6 text-[10px] w-full">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="SUM" className="text-[10px]">SUM (합계)</SelectItem>
                <SelectItem value="COUNT" className="text-[10px]">COUNT (개수)</SelectItem>
                <SelectItem value="AVG" className="text-[10px]">AVG (평균)</SelectItem>
                <SelectItem value="MIN" className="text-[10px]">MIN (최소)</SelectItem>
                <SelectItem value="MAX" className="text-[10px]">MAX (최대)</SelectItem>
                <SelectItem value="VALUE" className="text-[10px]">VALUE (값)</SelectItem>
              </SelectContent>
            </Select>
          </div>
          <div className="flex items-end">
            <Button
              size="sm"
              variant="outline"
              onClick={addColumnAgg}
              disabled={!newTokenColumn}
              className="h-6 text-[9px] px-3"
            >
              <Plus className="h-3 w-3 mr-1" />
              추가
            </Button>
          </div>
        </div>
        
        {newTokenTable !== sourceTable && newTokenTable && (
          <p className="text-[8px] text-orange-600">외부 테이블: _EXT 함수 사용</p>
        )}
      </div>

      {/* 수동 입력 모드 토글 */}
      <details className="text-[9px]">
        <summary className="cursor-pointer text-muted-foreground hover:text-foreground">
          수동 입력 모드
        </summary>
        <div className="mt-1 space-y-1">
          <Input
            value={tokensToFormula(tokens)}
            onChange={(e) => {
              const parsed = parseFormulaToTokens(e.target.value, sourceTable);
              setTokens(parsed);
              onChange(e.target.value);
            }}
            placeholder="{total_balance} - SUM_EXT({plan_qty})"
            className="h-6 text-[10px] font-mono"
          />
          <p className="text-[8px] text-muted-foreground">
            직접 수식 입력. 예: {"{"}resultField{"}"}, SUM({"{"}column{"}"}), SUM_EXT({"{"}column{"}"})
          </p>
        </div>
      </details>
    </div>
  );
}

// 🆕 집계 설정 전용 모달
function AggregationSettingsModal({
  open,
  onOpenChange,
  aggregations,
  sourceTable,
  allTables,
  contentRows,
  onSave,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  aggregations: AggregationConfig[];
  sourceTable: string;
  allTables: { tableName: string; displayName?: string }[];
  contentRows: CardContentRowConfig[];
  onSave: (aggregations: AggregationConfig[]) => void;
}) {
  // 로컬 상태로 집계 목록 관리
  const [localAggregations, setLocalAggregations] = useState<AggregationConfig[]>(aggregations);
  
  // 모달 열릴 때 초기화
  useEffect(() => {
    if (open) {
      setLocalAggregations(aggregations);
    }
  }, [open, aggregations]);

  // 집계 추가
  const addAggregation = (type: "column" | "formula") => {
    const newAgg: AggregationConfig = {
      sourceType: type,
      resultField: `agg_${Date.now()}`,
      label: type === "column" ? "새 집계" : "새 가상 집계",
      ...(type === "column" ? { type: "sum", sourceField: "", sourceTable: sourceTable } : { formula: "" }),
    };
    setLocalAggregations([...localAggregations, newAgg]);
  };

  // 집계 삭제
  const removeAggregation = (index: number) => {
    const newAggs = [...localAggregations];
    newAggs.splice(index, 1);
    setLocalAggregations(newAggs);
  };

  // 집계 업데이트
  const updateAggregation = (index: number, updates: Partial<AggregationConfig>) => {
    const newAggs = [...localAggregations];
    newAggs[index] = { ...newAggs[index], ...updates };
    setLocalAggregations(newAggs);
  };

  // 집계 순서 변경
  const moveAggregation = (index: number, direction: "up" | "down") => {
    const newIndex = direction === "up" ? index - 1 : index + 1;
    if (newIndex < 0 || newIndex >= localAggregations.length) return;
    
    const newAggs = [...localAggregations];
    [newAggs[index], newAggs[newIndex]] = [newAggs[newIndex], newAggs[index]];
    setLocalAggregations(newAggs);
  };

  // 저장
  const handleSave = () => {
    onSave(localAggregations);
    onOpenChange(false);
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-[95vw] sm:max-w-[700px] max-h-[85vh] flex flex-col p-0">
        <DialogHeader className="px-4 pt-4 pb-2 border-b shrink-0">
          <DialogTitle className="text-base">집계 설정</DialogTitle>
          <DialogDescription className="text-xs">
            그룹 내 데이터의 합계, 개수, 평균 등을 계산합니다. 가상 집계는 다른 집계 결과를 참조하여 연산할 수 있습니다.
          </DialogDescription>
        </DialogHeader>

        <div className="flex-1 overflow-hidden px-4">
          <ScrollArea className="h-[calc(85vh-180px)]">
            <div className="space-y-3 py-3 pr-3">
              {/* 집계 추가 버튼 */}
              <div className="flex gap-2 sticky top-0 bg-background z-10 pb-2">
                <Button
                  size="sm"
                  variant="outline"
                  onClick={() => addAggregation("column")}
                  className="h-8 text-xs flex-1"
                >
                  <Plus className="h-3 w-3 mr-1" />
                  컬럼 집계 추가
                </Button>
                <Button
                  size="sm"
                  variant="outline"
                  onClick={() => addAggregation("formula")}
                  className="h-8 text-xs flex-1 bg-purple-50 hover:bg-purple-100 border-purple-200"
                >
                  <Plus className="h-3 w-3 mr-1" />
                  가상 집계 추가
                </Button>
              </div>

              {/* 집계 목록 */}
              {localAggregations.length === 0 ? (
                <div className="text-center py-8 border border-dashed rounded-lg">
                  <p className="text-sm text-muted-foreground mb-2">집계 설정이 없습니다</p>
                  <p className="text-xs text-muted-foreground">
                    위의 버튼으로 컬럼 집계 또는 가상 집계를 추가하세요
                  </p>
                </div>
              ) : (
                <div className="space-y-3">
                  {localAggregations.map((agg, index) => (
                    <AggregationConfigItemModal
                      key={`agg-modal-${index}`}
                      agg={agg}
                      index={index}
                      totalCount={localAggregations.length}
                      sourceTable={sourceTable}
                      allTables={allTables}
                      existingAggregations={localAggregations}
                      contentRows={contentRows}
                      onUpdate={(updates) => updateAggregation(index, updates)}
                      onRemove={() => removeAggregation(index)}
                      onMove={(direction) => moveAggregation(index, direction)}
                    />
                  ))}
                </div>
              )}
            </div>
          </ScrollArea>
        </div>

        <DialogFooter className="px-4 py-3 border-t shrink-0">
          <Button variant="outline" onClick={() => onOpenChange(false)} className="h-9 text-sm">
            취소
          </Button>
          <Button onClick={handleSave} className="h-9 text-sm">
            저장 ({localAggregations.length}개)
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

// 집계 설정 아이템 (모달용 - 더 넓은 공간 활용)
function AggregationConfigItemModal({
  agg,
  index,
  totalCount,
  sourceTable,
  allTables,
  existingAggregations,
  contentRows,
  onUpdate,
  onRemove,
  onMove,
}: {
  agg: AggregationConfig;
  index: number;
  totalCount: number;
  sourceTable: string;
  allTables: { tableName: string; displayName?: string }[];
  existingAggregations: AggregationConfig[];
  contentRows: CardContentRowConfig[];
  onUpdate: (updates: Partial<AggregationConfig>) => void;
  onRemove: () => void;
  onMove: (direction: "up" | "down") => void;
}) {
  const [localLabel, setLocalLabel] = useState(agg.label || "");
  const [localResultField, setLocalResultField] = useState(agg.resultField || "");
  const [localFormula, setLocalFormula] = useState(agg.formula || "");

  useEffect(() => {
    setLocalLabel(agg.label || "");
    setLocalResultField(agg.resultField || "");
    setLocalFormula(agg.formula || "");
  }, [agg.label, agg.resultField, agg.formula]);

  // 현재 집계보다 앞에 정의된 집계들만 참조 가능 (순환 참조 방지)
  const referenceableAggregations = existingAggregations.slice(0, index);

  const currentSourceType = agg.sourceType || "column";
  const isFormula = currentSourceType === "formula";

  return (
    <div className={cn(
      "border rounded-lg p-4 space-y-4",
      isFormula ? "bg-purple-50 dark:bg-purple-950 border-purple-200" : "bg-blue-50 dark:bg-blue-950 border-blue-200"
    )}>
      {/* 헤더 */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          {/* 순서 변경 버튼 */}
          <div className="flex flex-col">
            <Button
              size="sm"
              variant="ghost"
              onClick={() => onMove("up")}
              disabled={index === 0}
              className="h-4 w-6 p-0"
            >
              <ChevronUp className="h-3 w-3" />
            </Button>
            <Button
              size="sm"
              variant="ghost"
              onClick={() => onMove("down")}
              disabled={index === totalCount - 1}
              className="h-4 w-6 p-0"
            >
              <ChevronDown className="h-3 w-3" />
            </Button>
          </div>
          <Badge className={cn(
            "text-xs px-2 py-0.5",
            isFormula ? "bg-purple-100 text-purple-700" : "bg-blue-100 text-blue-700"
          )}>
            {isFormula ? "가상" : "집계"} {index + 1}
          </Badge>
          <span className="text-sm font-medium">{agg.label || "(라벨 없음)"}</span>
        </div>
        <Button size="sm" variant="ghost" onClick={onRemove} className="h-7 w-7 p-0 hover:bg-destructive/10 hover:text-destructive">
          <X className="h-4 w-4" />
        </Button>
      </div>

      {/* 집계 타입 선택 */}
      <div className="grid grid-cols-2 gap-4">
        <div className="space-y-1.5">
          <Label className="text-xs">집계 타입</Label>
          <Select
            value={currentSourceType}
            onValueChange={(value) => onUpdate({ sourceType: value as "column" | "formula" })}
          >
            <SelectTrigger className="h-9 text-sm">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="column">컬럼 집계 (SUM, COUNT 등)</SelectItem>
              <SelectItem value="formula">가상 집계 (연산식)</SelectItem>
            </SelectContent>
          </Select>
        </div>

        <div className="space-y-1.5">
          <Label className="text-xs">결과 필드명 *</Label>
          <Input
            value={localResultField}
            onChange={(e) => setLocalResultField(e.target.value)}
            onBlur={() => onUpdate({ resultField: localResultField })}
            placeholder="예: total_order_qty"
            className="h-9 text-sm"
          />
        </div>
      </div>

      {/* 컬럼 집계 설정 */}
      {!isFormula && (
        <div className="grid grid-cols-3 gap-4">
          <div className="space-y-1.5">
            <Label className="text-xs">테이블</Label>
            <Select
              value={agg.sourceTable || sourceTable}
              onValueChange={(value) => onUpdate({ sourceTable: value })}
            >
              <SelectTrigger className="h-9 text-sm">
                <SelectValue placeholder="테이블 선택" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value={sourceTable}>{sourceTable} (기본)</SelectItem>
                {allTables.filter(t => t.tableName !== sourceTable).map((table) => (
                  <SelectItem key={table.tableName} value={table.tableName}>
                    {table.displayName || table.tableName}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          <div className="space-y-1.5">
            <Label className="text-xs">컬럼</Label>
            <SourceColumnSelector
              sourceTable={agg.sourceTable || sourceTable}
              value={agg.sourceField || ""}
              onChange={(value) => onUpdate({ sourceField: value })}
              placeholder="컬럼 선택"
            />
          </div>

          <div className="space-y-1.5">
            <Label className="text-xs">집계 함수</Label>
            <Select
              value={agg.type || "sum"}
              onValueChange={(value) => onUpdate({ type: value as AggregationConfig["type"] })}
            >
              <SelectTrigger className="h-9 text-sm">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="sum">합계 (SUM)</SelectItem>
                <SelectItem value="count">개수 (COUNT)</SelectItem>
                <SelectItem value="avg">평균 (AVG)</SelectItem>
                <SelectItem value="min">최소 (MIN)</SelectItem>
                <SelectItem value="max">최대 (MAX)</SelectItem>
              </SelectContent>
            </Select>
          </div>
        </div>
      )}

      {/* 가상 집계 (연산식) 설정 */}
      {isFormula && (
        <div className="space-y-3">
          <div className="space-y-1.5">
            <Label className="text-xs">연산식</Label>
            <div className="p-3 bg-background rounded-lg border min-h-[60px]">
              <code className="text-sm break-all">{localFormula || "아래에서 요소를 추가하세요"}</code>
            </div>
          </div>

          {/* 연산자 */}
          <div className="space-y-1.5">
            <Label className="text-xs">연산자</Label>
            <div className="flex gap-1 flex-wrap">
              {["+", "-", "*", "/", "(", ")"].map((op) => (
                <Button
                  key={op}
                  size="sm"
                  variant="outline"
                  onClick={() => {
                    const newFormula = localFormula + ` ${op} `;
                    setLocalFormula(newFormula);
                    onUpdate({ formula: newFormula });
                  }}
                  className="h-8 w-8 p-0 text-sm font-mono"
                >
                  {op}
                </Button>
              ))}
              <Button
                size="sm"
                variant="destructive"
                onClick={() => {
                  setLocalFormula("");
                  onUpdate({ formula: "" });
                }}
                className="h-8 px-2 text-xs ml-2"
              >
                초기화
              </Button>
            </div>
          </div>

          {/* 이전 집계 참조 */}
          {referenceableAggregations.length > 0 && (
            <div className="space-y-1.5 p-3 bg-blue-100 dark:bg-blue-900 rounded-lg">
              <Label className="text-xs text-blue-700 dark:text-blue-300">이전 집계 참조</Label>
              <div className="flex flex-wrap gap-1">
                {referenceableAggregations.map((refAgg) => (
                  <Button
                    key={refAgg.resultField}
                    size="sm"
                    variant="outline"
                    onClick={() => {
                      const newFormula = localFormula + `{${refAgg.resultField}}`;
                      setLocalFormula(newFormula);
                      onUpdate({ formula: newFormula });
                    }}
                    className="h-7 text-xs bg-blue-50 hover:bg-blue-100 border-blue-300"
                  >
                    {refAgg.label || refAgg.resultField}
                  </Button>
                ))}
              </div>
            </div>
          )}

          {/* 테이블 컬럼 집계 */}
          <div className="space-y-2 p-3 bg-green-100 dark:bg-green-900 rounded-lg">
            <Label className="text-xs text-green-700 dark:text-green-300">테이블 컬럼 집계</Label>
            <FormulaColumnAggregator
              sourceTable={sourceTable}
              allTables={allTables}
              onAdd={(formulaPart) => {
                const newFormula = localFormula + formulaPart;
                setLocalFormula(newFormula);
                onUpdate({ formula: newFormula });
              }}
            />
          </div>

          {/* 🆕 v3.11: SUM_EXT 참조 테이블 선택 */}
          {localFormula.includes("_EXT") && (
            <ExternalTableRefSelector
              contentRows={contentRows}
              selectedRefs={agg.externalTableRefs || []}
              onUpdate={(refs) => onUpdate({ externalTableRefs: refs })}
            />
          )}
        </div>
      )}

      {/* 라벨 및 숨김 설정 */}
      <div className="grid grid-cols-3 gap-4">
        <div className="space-y-1.5 col-span-2">
          <Label className="text-xs">표시 라벨 *</Label>
          <Input
            value={localLabel}
            onChange={(e) => setLocalLabel(e.target.value)}
            onBlur={() => onUpdate({ label: localLabel })}
            placeholder="예: 총수주량"
            className="h-9 text-sm"
          />
        </div>
        <div className="space-y-1.5">
          <Label className="text-xs">숨김</Label>
          <div className="flex items-center h-9 px-3 border rounded-md bg-background">
            <Switch
              checked={agg.hidden || false}
              onCheckedChange={(checked) => onUpdate({ hidden: checked })}
              className="scale-90"
            />
            <span className="ml-2 text-xs text-muted-foreground">
              {agg.hidden ? "숨김" : "표시"}
            </span>
          </div>
        </div>
      </div>
      {agg.hidden && (
        <p className="text-[10px] text-amber-600 bg-amber-50 px-2 py-1 rounded">
          이 집계는 연산에만 사용되며 레이아웃에서 선택할 수 없습니다.
        </p>
      )}
    </div>
  );
}

// 수식에 테이블 컬럼 집계 추가하는 컴포넌트
function FormulaColumnAggregator({
  sourceTable,
  allTables,
  onAdd,
}: {
  sourceTable: string;
  allTables: { tableName: string; displayName?: string }[];
  onAdd: (formulaPart: string) => void;
}) {
  // 데이터 소스 타입: "current" (현재 카드), "external" (외부 테이블 행)
  const [dataSourceType, setDataSourceType] = useState<"current" | "external">("current");
  const [selectedTable, setSelectedTable] = useState(sourceTable);
  const [selectedColumn, setSelectedColumn] = useState("");
  const [selectedFunction, setSelectedFunction] = useState<string>("SUM");

  // 데이터 소스 타입 변경 시 테이블 초기화
  useEffect(() => {
    if (dataSourceType === "current") {
      setSelectedTable(sourceTable);
    }
  }, [dataSourceType, sourceTable]);

  const handleAdd = () => {
    if (!selectedColumn) return;
    
    // 외부 데이터는 항상 _EXT 접미사 사용
    const funcName = dataSourceType === "external" ? `${selectedFunction}_EXT` : selectedFunction;
    const formulaPart = `${funcName}({${selectedColumn}})`;
    onAdd(formulaPart);
    setSelectedColumn("");
  };

  return (
    <div className="space-y-2">
      {/* 데이터 소스 선택 */}
      <div className="grid grid-cols-2 gap-2">
        <Button
          size="sm"
          variant={dataSourceType === "current" ? "default" : "outline"}
          onClick={() => setDataSourceType("current")}
          className="h-7 text-xs"
        >
          현재 카드 데이터
        </Button>
        <Button
          size="sm"
          variant={dataSourceType === "external" ? "default" : "outline"}
          onClick={() => setDataSourceType("external")}
          className="h-7 text-xs bg-amber-100 hover:bg-amber-200 text-amber-800 border-amber-300"
        >
          외부 테이블 데이터
        </Button>
      </div>
      
      {dataSourceType === "external" && (
        <p className="text-[10px] text-amber-600 bg-amber-50 px-2 py-1 rounded">
          레이아웃의 테이블 행에서 조회한 외부 데이터를 집계합니다 (같은 품목의 다른 수주 등)
        </p>
      )}

      <div className="grid grid-cols-3 gap-2">
        <div className="space-y-1">
          <Label className="text-[10px]">테이블</Label>
          <Select 
            value={selectedTable} 
            onValueChange={setSelectedTable}
            disabled={dataSourceType === "current"}
          >
            <SelectTrigger className="h-7 text-xs">
              <SelectValue placeholder="테이블" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value={sourceTable}>{sourceTable}</SelectItem>
              {allTables.filter(t => t.tableName !== sourceTable).map((table) => (
                <SelectItem key={table.tableName} value={table.tableName}>
                  {table.displayName || table.tableName}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>

        <div className="space-y-1">
          <Label className="text-[10px]">컬럼</Label>
          <SourceColumnSelector
            sourceTable={selectedTable}
            value={selectedColumn}
            onChange={setSelectedColumn}
            placeholder="컬럼"
          />
        </div>

        <div className="space-y-1">
          <Label className="text-[10px]">함수</Label>
          <Select value={selectedFunction} onValueChange={setSelectedFunction}>
            <SelectTrigger className="h-7 text-xs">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="SUM">SUM</SelectItem>
              <SelectItem value="COUNT">COUNT</SelectItem>
              <SelectItem value="AVG">AVG</SelectItem>
              <SelectItem value="MIN">MIN</SelectItem>
              <SelectItem value="MAX">MAX</SelectItem>
            </SelectContent>
          </Select>
        </div>
      </div>

      <Button
        size="sm"
        onClick={handleAdd}
        disabled={!selectedColumn}
        className="h-7 text-xs w-full"
      >
        {dataSourceType === "external" ? `${selectedFunction}_EXT` : selectedFunction}({selectedColumn || "컬럼"}) 추가
      </Button>
    </div>
  );
}

// 🆕 v3.11: SUM_EXT 참조 테이블 선택 컴포넌트
function ExternalTableRefSelector({
  contentRows,
  selectedRefs,
  onUpdate,
}: {
  contentRows: CardContentRowConfig[];
  selectedRefs: string[];
  onUpdate: (refs: string[]) => void;
}) {
  // 외부 데이터 소스가 활성화된 테이블 행만 필터링
  const tableRowsWithExternalSource = contentRows.filter(
    (row) => row.type === "table" && row.tableDataSource?.enabled
  );

  if (tableRowsWithExternalSource.length === 0) {
    return (
      <div className="p-3 bg-gray-100 dark:bg-gray-800 rounded-lg">
        <p className="text-xs text-muted-foreground">
          레이아웃에 외부 데이터 소스가 설정된 테이블 행이 없습니다.
        </p>
      </div>
    );
  }

  const isAllSelected = selectedRefs.length === 0;

  const handleToggleTable = (tableId: string) => {
    if (selectedRefs.includes(tableId)) {
      // 이미 선택된 경우 제거
      const newRefs = selectedRefs.filter((id) => id !== tableId);
      onUpdate(newRefs);
    } else {
      // 선택되지 않은 경우 추가
      onUpdate([...selectedRefs, tableId]);
    }
  };

  const handleSelectAll = () => {
    onUpdate([]); // 빈 배열 = 모든 테이블 사용
  };

  return (
    <div className="p-3 bg-amber-50 dark:bg-amber-950 rounded-lg border border-amber-200 space-y-2">
      <div className="flex items-center justify-between">
        <Label className="text-xs text-amber-700 dark:text-amber-300 font-medium">
          SUM_EXT 참조 테이블 (외부 데이터 소스)
        </Label>
        <Button
          size="sm"
          variant={isAllSelected ? "default" : "outline"}
          onClick={handleSelectAll}
          className="h-6 text-[10px] px-2"
        >
          전체 선택
        </Button>
      </div>
      
      <p className="text-[10px] text-amber-600">
        SUM_EXT 함수가 참조할 테이블을 선택하세요. 선택하지 않으면 모든 외부 테이블 데이터를 사용합니다.
      </p>

      <div className="space-y-1">
        {tableRowsWithExternalSource.map((row) => {
          const isSelected = selectedRefs.length === 0 || selectedRefs.includes(row.id);
          const tableTitle = row.title || row.tableDataSource?.sourceTable || row.id;
          const tableName = row.tableDataSource?.sourceTable || "";

          return (
            <div
              key={row.id}
              className={cn(
                "flex items-center gap-2 p-2 rounded border cursor-pointer transition-colors",
                isSelected
                  ? "bg-amber-100 border-amber-300"
                  : "bg-white border-gray-200 hover:bg-gray-50"
              )}
              onClick={() => handleToggleTable(row.id)}
            >
              <input
                type="checkbox"
                checked={isSelected}
                onChange={() => {}} // onClick에서 처리
                className="h-4 w-4 rounded border-gray-300 text-amber-600 focus:ring-amber-500"
              />
              <div className="flex-1 min-w-0">
                <p className="text-xs font-medium truncate">{tableTitle}</p>
                <p className="text-[10px] text-muted-foreground truncate">
                  테이블: {tableName} | ID: {row.id.slice(-10)}
                </p>
              </div>
            </div>
          );
        })}
      </div>

      {selectedRefs.length > 0 && (
        <p className="text-[10px] text-amber-700 bg-amber-100 px-2 py-1 rounded">
          선택된 테이블: {selectedRefs.length}개 (특정 테이블만 참조)
        </p>
      )}
    </div>
  );
}

// 🆕 v3.12: 연동 저장 설정 섹션
function SyncSaveConfigSection({
  row,
  allTables,
  onUpdateRow,
}: {
  row: CardContentRowConfig;
  allTables: { tableName: string; displayName?: string }[];
  onUpdateRow: (updates: Partial<CardContentRowConfig>) => void;
}) {
  const syncSaves = row.tableCrud?.syncSaves || [];
  const sourceTable = row.tableDataSource?.sourceTable || "";

  // 연동 저장 추가
  const addSyncSave = () => {
    const newSyncSave: SyncSaveConfig = {
      id: `sync-${Date.now()}`,
      enabled: true,
      sourceColumn: "",
      aggregationType: "sum",
      targetTable: "",
      targetColumn: "",
      joinKey: {
        sourceField: "",
        targetField: "id",
      },
    };
    
    onUpdateRow({
      tableCrud: {
        ...row.tableCrud,
        allowCreate: row.tableCrud?.allowCreate || false,
        allowUpdate: row.tableCrud?.allowUpdate || false,
        allowDelete: row.tableCrud?.allowDelete || false,
        syncSaves: [...syncSaves, newSyncSave],
      },
    });
  };

  // 연동 저장 삭제
  const removeSyncSave = (index: number) => {
    const newSyncSaves = [...syncSaves];
    newSyncSaves.splice(index, 1);
    
    onUpdateRow({
      tableCrud: {
        ...row.tableCrud,
        allowCreate: row.tableCrud?.allowCreate || false,
        allowUpdate: row.tableCrud?.allowUpdate || false,
        allowDelete: row.tableCrud?.allowDelete || false,
        syncSaves: newSyncSaves,
      },
    });
  };

  // 연동 저장 업데이트
  const updateSyncSave = (index: number, updates: Partial<SyncSaveConfig>) => {
    const newSyncSaves = [...syncSaves];
    newSyncSaves[index] = { ...newSyncSaves[index], ...updates };
    
    onUpdateRow({
      tableCrud: {
        ...row.tableCrud,
        allowCreate: row.tableCrud?.allowCreate || false,
        allowUpdate: row.tableCrud?.allowUpdate || false,
        allowDelete: row.tableCrud?.allowDelete || false,
        syncSaves: newSyncSaves,
      },
    });
  };

  return (
    <div className="space-y-2 p-2 bg-orange-50 dark:bg-orange-950 rounded-lg border border-orange-200">
      <div className="flex items-center justify-between">
        <Label className="text-[10px] font-semibold text-orange-700 dark:text-orange-300">
          연동 저장 설정 (모달 저장 시 다른 테이블에 동기화)
        </Label>
        <Button
          size="sm"
          variant="outline"
          onClick={addSyncSave}
          className="h-5 text-[9px] px-1 bg-orange-100 hover:bg-orange-200 border-orange-300"
        >
          <Plus className="h-2 w-2 mr-0.5" />
          추가
        </Button>
      </div>

      {syncSaves.length === 0 ? (
        <p className="text-[9px] text-muted-foreground text-center py-2">
          연동 저장 설정이 없습니다. 추가 버튼을 눌러 설정하세요.
        </p>
      ) : (
        <div className="space-y-2">
          {syncSaves.map((sync, index) => (
            <SyncSaveConfigItem
              key={sync.id}
              sync={sync}
              index={index}
              sourceTable={sourceTable}
              allTables={allTables}
              onUpdate={(updates) => updateSyncSave(index, updates)}
              onRemove={() => removeSyncSave(index)}
            />
          ))}
        </div>
      )}
    </div>
  );
}

// 🆕 v3.12: 개별 연동 저장 설정 아이템
function SyncSaveConfigItem({
  sync,
  index,
  sourceTable,
  allTables,
  onUpdate,
  onRemove,
}: {
  sync: SyncSaveConfig;
  index: number;
  sourceTable: string;
  allTables: { tableName: string; displayName?: string }[];
  onUpdate: (updates: Partial<SyncSaveConfig>) => void;
  onRemove: () => void;
}) {
  return (
    <div className={cn(
      "p-2 rounded border space-y-2",
      sync.enabled ? "bg-orange-100 border-orange-300" : "bg-gray-100 border-gray-300 opacity-60"
    )}>
      {/* 헤더 */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <Switch
            checked={sync.enabled}
            onCheckedChange={(checked) => onUpdate({ enabled: checked })}
            className="scale-[0.6]"
          />
          <Badge className="text-[8px] px-1 py-0 bg-orange-200 text-orange-800">
            연동 {index + 1}
          </Badge>
        </div>
        <Button
          size="sm"
          variant="ghost"
          onClick={onRemove}
          className="h-4 w-4 p-0 hover:bg-destructive/10 hover:text-destructive"
        >
          <X className="h-3 w-3" />
        </Button>
      </div>

      {/* 소스 설정 */}
      <div className="grid grid-cols-2 gap-2">
        <div className="space-y-0.5">
          <Label className="text-[8px] text-muted-foreground">소스 컬럼 ({sourceTable})</Label>
          <SourceColumnSelector
            sourceTable={sourceTable}
            value={sync.sourceColumn}
            onChange={(value) => onUpdate({ sourceColumn: value })}
            placeholder="컬럼 선택"
          />
        </div>
        <div className="space-y-0.5">
          <Label className="text-[8px] text-muted-foreground">집계 방식</Label>
          <Select
            value={sync.aggregationType}
            onValueChange={(value) => onUpdate({ aggregationType: value as SyncSaveConfig["aggregationType"] })}
          >
            <SelectTrigger className="h-6 text-[10px]">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="sum">합계 (SUM)</SelectItem>
              <SelectItem value="count">개수 (COUNT)</SelectItem>
              <SelectItem value="avg">평균 (AVG)</SelectItem>
              <SelectItem value="min">최소 (MIN)</SelectItem>
              <SelectItem value="max">최대 (MAX)</SelectItem>
              <SelectItem value="latest">최신값 (LATEST)</SelectItem>
            </SelectContent>
          </Select>
        </div>
      </div>

      {/* 대상 설정 */}
      <div className="grid grid-cols-2 gap-2">
        <div className="space-y-0.5">
          <Label className="text-[8px] text-muted-foreground">대상 테이블</Label>
          <Select
            value={sync.targetTable}
            onValueChange={(value) => onUpdate({ targetTable: value })}
          >
            <SelectTrigger className="h-6 text-[10px]">
              <SelectValue placeholder="테이블 선택" />
            </SelectTrigger>
            <SelectContent>
              {allTables.map((table) => (
                <SelectItem key={table.tableName} value={table.tableName}>
                  {table.displayName || table.tableName}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
        <div className="space-y-0.5">
          <Label className="text-[8px] text-muted-foreground">대상 컬럼</Label>
          <SourceColumnSelector
            sourceTable={sync.targetTable}
            value={sync.targetColumn}
            onChange={(value) => onUpdate({ targetColumn: value })}
            placeholder="컬럼 선택"
          />
        </div>
      </div>

      {/* 조인 키 설정 */}
      <div className="grid grid-cols-2 gap-2">
        <div className="space-y-0.5">
          <Label className="text-[8px] text-muted-foreground">조인 키 (소스)</Label>
          <SourceColumnSelector
            sourceTable={sourceTable}
            value={sync.joinKey.sourceField}
            onChange={(value) => onUpdate({ joinKey: { ...sync.joinKey, sourceField: value } })}
            placeholder="예: sales_order_id"
          />
        </div>
        <div className="space-y-0.5">
          <Label className="text-[8px] text-muted-foreground">조인 키 (대상)</Label>
          <SourceColumnSelector
            sourceTable={sync.targetTable}
            value={sync.joinKey.targetField}
            onChange={(value) => onUpdate({ joinKey: { ...sync.joinKey, targetField: value } })}
            placeholder="예: id"
          />
        </div>
      </div>

      {/* 설정 요약 */}
      {sync.sourceColumn && sync.targetTable && sync.targetColumn && (
        <p className="text-[8px] text-orange-700 bg-orange-200 px-2 py-1 rounded">
          {sourceTable}.{sync.sourceColumn}의 {sync.aggregationType.toUpperCase()} 값을{" "}
          {sync.targetTable}.{sync.targetColumn}에 저장
        </p>
      )}
    </div>
  );
}

// 🆕 v3.13: 행 추가 시 자동 채번 설정 섹션
function RowNumberingConfigSection({
  row,
  onUpdateRow,
}: {
  row: CardContentRowConfig;
  onUpdateRow: (updates: Partial<CardContentRowConfig>) => void;
}) {
  const [numberingRules, setNumberingRules] = useState<{ id: string; name: string; code: string }[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  
  const rowNumbering = row.tableCrud?.rowNumbering;
  const tableColumns = row.tableColumns || [];

  // 채번 규칙 목록 로드 (옵션설정 > 코드설정에서 등록된 전체 목록)
  useEffect(() => {
    const loadNumberingRules = async () => {
      setIsLoading(true);
      try {
        const { getNumberingRules } = await import("@/lib/api/numberingRule");
        const response = await getNumberingRules();
        if (response.success && response.data) {
          setNumberingRules(response.data.map((rule: any, index: number) => ({
            id: String(rule.ruleId || rule.id || `rule-${index}`),
            name: rule.ruleName || rule.name || "이름 없음",
            code: rule.ruleId || rule.code || "",
          })));
        }
      } catch (error) {
        console.error("채번 규칙 로드 실패:", error);
        setNumberingRules([]);
      } finally {
        setIsLoading(false);
      }
    };
    loadNumberingRules();
  }, []);

  // 채번 설정 업데이트
  const updateRowNumbering = (updates: Partial<RowNumberingConfig>) => {
    const currentNumbering = row.tableCrud?.rowNumbering || {
      enabled: false,
      targetColumn: "",
      numberingRuleId: "",
    };
    
    onUpdateRow({
      tableCrud: {
        ...row.tableCrud,
        allowCreate: row.tableCrud?.allowCreate || false,
        allowUpdate: row.tableCrud?.allowUpdate || false,
        allowDelete: row.tableCrud?.allowDelete || false,
        rowNumbering: {
          ...currentNumbering,
          ...updates,
        },
      },
    });
  };

  return (
    <div className="space-y-2 p-3 bg-purple-50 dark:bg-purple-950 rounded-lg border border-purple-200">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <Switch
            checked={rowNumbering?.enabled || false}
            onCheckedChange={(checked) => updateRowNumbering({ enabled: checked })}
            className="scale-90"
          />
          <Label className="text-xs font-semibold text-purple-700 dark:text-purple-300">
            행 추가 시 자동 채번
          </Label>
        </div>
      </div>

      <p className="text-[10px] text-purple-600 leading-tight">
        &quot;추가&quot; 버튼 클릭 시 지정한 컬럼에 자동으로 번호를 생성합니다.
        (옵션설정 &gt; 코드설정에서 등록한 채번 규칙 사용)
      </p>

      {rowNumbering?.enabled && (
        <div className="space-y-3 pt-2 border-t border-purple-200">
          {/* 대상 컬럼 선택 */}
          <div className="space-y-1">
            <Label className="text-[10px] text-purple-700">채번 대상 컬럼 *</Label>
            <Select
              value={rowNumbering.targetColumn || ""}
              onValueChange={(value) => updateRowNumbering({ targetColumn: value })}
            >
              <SelectTrigger className="h-8 text-xs">
                <SelectValue placeholder="컬럼 선택" />
              </SelectTrigger>
              <SelectContent>
                {tableColumns
                  .filter((col) => col.field && col.field.trim() !== "")
                  .map((col, index) => (
                    <SelectItem key={col.id || `col-${index}`} value={col.field} className="text-xs">
                      {col.label || col.field}
                    </SelectItem>
                  ))}
              </SelectContent>
            </Select>
            <p className="text-[9px] text-muted-foreground">
              채번 결과가 저장될 컬럼 (수정 가능 여부는 컬럼 설정에서 조절)
            </p>
          </div>

          {/* 채번 규칙 선택 */}
          <div className="space-y-1">
            <Label className="text-[10px] text-purple-700">채번 규칙 *</Label>
            <Select
              value={rowNumbering.numberingRuleId || ""}
              onValueChange={(value) => updateRowNumbering({ numberingRuleId: value })}
              disabled={isLoading}
            >
              <SelectTrigger className="h-8 text-xs">
                <SelectValue placeholder={isLoading ? "로딩 중..." : "채번 규칙 선택"} />
              </SelectTrigger>
              <SelectContent>
                {numberingRules.map((rule) => (
                  <SelectItem key={rule.id} value={rule.id} className="text-xs">
                    {rule.name} ({rule.code})
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            {numberingRules.length === 0 && !isLoading && (
              <p className="text-[9px] text-amber-600">
                등록된 채번 규칙이 없습니다. 옵션설정 &gt; 코드설정에서 추가하세요.
              </p>
            )}
          </div>

          {/* 설정 요약 */}
          {rowNumbering.targetColumn && rowNumbering.numberingRuleId && (
            <div className="text-[10px] text-purple-700 bg-purple-100 px-2 py-1.5 rounded">
              "추가" 클릭 시 <strong>{rowNumbering.targetColumn}</strong> 컬럼에 자동 채번
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// 🆕 레이아웃 설정 전용 모달
function LayoutSettingsModal({
  open,
  onOpenChange,
  contentRows,
  allTables,
  dataSourceTable,
  aggregations,
  onSave,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  contentRows: CardContentRowConfig[];
  allTables: { tableName: string; displayName?: string }[];
  dataSourceTable: string;
  aggregations: AggregationConfig[];
  onSave: (contentRows: CardContentRowConfig[]) => void;
}) {
  // 로컬 상태로 행 목록 관리
  const [localRows, setLocalRows] = useState<CardContentRowConfig[]>(contentRows);
  
  // 모달 열릴 때 초기화
  useEffect(() => {
    if (open) {
      setLocalRows(contentRows);
    }
  }, [open, contentRows]);

  // 행 추가
  const addRow = (type: CardContentRowConfig["type"]) => {
    const newRow: CardContentRowConfig = {
      id: `crow-${Date.now()}`,
      type,
      ...(type === "header" || type === "fields"
        ? { columns: [], layout: "horizontal", gap: "16px" }
        : {}),
      ...(type === "aggregation"
        ? { aggregationFields: [], aggregationLayout: "horizontal" }
        : {}),
      ...(type === "table"
        ? { tableColumns: [], showTableHeader: true }
        : {}),
    };
    setLocalRows([...localRows, newRow]);
  };

  // 행 삭제
  const removeRow = (index: number) => {
    const newRows = [...localRows];
    newRows.splice(index, 1);
    setLocalRows(newRows);
  };

  // 행 업데이트
  const updateRow = (index: number, updates: Partial<CardContentRowConfig>) => {
    const newRows = [...localRows];
    newRows[index] = { ...newRows[index], ...updates };
    setLocalRows(newRows);
  };

  // 행 순서 변경
  const moveRow = (index: number, direction: "up" | "down") => {
    const newIndex = direction === "up" ? index - 1 : index + 1;
    if (newIndex < 0 || newIndex >= localRows.length) return;
    
    const newRows = [...localRows];
    [newRows[index], newRows[newIndex]] = [newRows[newIndex], newRows[index]];
    setLocalRows(newRows);
  };

  // 컬럼 추가 (header/fields용)
  const addColumn = (rowIndex: number) => {
    const newRows = [...localRows];
    const newCol: CardColumnConfig = {
      id: `col-${Date.now()}`,
      field: "",
      label: "",
      type: "text",
      width: "auto",
      editable: false,
    };
    newRows[rowIndex].columns = [...(newRows[rowIndex].columns || []), newCol];
    setLocalRows(newRows);
  };

  // 컬럼 삭제
  const removeColumn = (rowIndex: number, colIndex: number) => {
    const newRows = [...localRows];
    newRows[rowIndex].columns?.splice(colIndex, 1);
    setLocalRows(newRows);
  };

  // 컬럼 업데이트
  const updateColumn = (rowIndex: number, colIndex: number, updates: Partial<CardColumnConfig>) => {
    const newRows = [...localRows];
    if (newRows[rowIndex].columns) {
      newRows[rowIndex].columns![colIndex] = {
        ...newRows[rowIndex].columns![colIndex],
        ...updates,
      };
    }
    setLocalRows(newRows);
  };

  // 집계 필드 추가
  const addAggField = (rowIndex: number) => {
    const newRows = [...localRows];
    const newAggField: AggregationDisplayConfig = {
      aggregationResultField: "",
      label: "",
    };
    newRows[rowIndex].aggregationFields = [...(newRows[rowIndex].aggregationFields || []), newAggField];
    setLocalRows(newRows);
  };

  // 집계 필드 삭제
  const removeAggField = (rowIndex: number, fieldIndex: number) => {
    const newRows = [...localRows];
    newRows[rowIndex].aggregationFields?.splice(fieldIndex, 1);
    setLocalRows(newRows);
  };

  // 집계 필드 업데이트
  const updateAggField = (rowIndex: number, fieldIndex: number, updates: Partial<AggregationDisplayConfig>) => {
    const newRows = [...localRows];
    if (newRows[rowIndex].aggregationFields) {
      newRows[rowIndex].aggregationFields![fieldIndex] = {
        ...newRows[rowIndex].aggregationFields![fieldIndex],
        ...updates,
      };
    }
    setLocalRows(newRows);
  };

  // 집계 필드 순서 변경
  const moveAggField = (rowIndex: number, fieldIndex: number, direction: "up" | "down") => {
    const newRows = [...localRows];
    const fields = newRows[rowIndex].aggregationFields;
    if (!fields) return;

    const newIndex = direction === "up" ? fieldIndex - 1 : fieldIndex + 1;
    if (newIndex < 0 || newIndex >= fields.length) return;

    [fields[fieldIndex], fields[newIndex]] = [fields[newIndex], fields[fieldIndex]];
    setLocalRows(newRows);
  };

  // 테이블 컬럼 추가
  const addTableColumn = (rowIndex: number) => {
    const newRows = [...localRows];
    const newCol: TableColumnConfig = {
      id: `tcol-${Date.now()}`,
      field: "",
      label: "",
      type: "text",
      editable: false,
    };
    newRows[rowIndex].tableColumns = [...(newRows[rowIndex].tableColumns || []), newCol];
    setLocalRows(newRows);
  };

  // 테이블 컬럼 삭제
  const removeTableColumn = (rowIndex: number, colIndex: number) => {
    const newRows = [...localRows];
    newRows[rowIndex].tableColumns?.splice(colIndex, 1);
    setLocalRows(newRows);
  };

  // 테이블 컬럼 업데이트
  const updateTableColumn = (rowIndex: number, colIndex: number, updates: Partial<TableColumnConfig>) => {
    const newRows = [...localRows];
    if (newRows[rowIndex].tableColumns) {
      newRows[rowIndex].tableColumns![colIndex] = {
        ...newRows[rowIndex].tableColumns![colIndex],
        ...updates,
      };
    }
    setLocalRows(newRows);
  };

  // 테이블 컬럼 순서 변경
  const moveTableColumn = (rowIndex: number, colIndex: number, direction: "up" | "down") => {
    const newRows = [...localRows];
    const cols = newRows[rowIndex].tableColumns;
    if (!cols) return;

    const newIndex = direction === "up" ? colIndex - 1 : colIndex + 1;
    if (newIndex < 0 || newIndex >= cols.length) return;

    [cols[colIndex], cols[newIndex]] = [cols[newIndex], cols[colIndex]];
    setLocalRows(newRows);
  };

  // 저장
  const handleSave = () => {
    onSave(localRows);
    onOpenChange(false);
  };

  // 행 타입별 색상
  const getRowTypeColor = (type: CardContentRowConfig["type"]) => {
    switch (type) {
      case "header": return "bg-blue-100 border-blue-300";
      case "aggregation": return "bg-orange-100 border-orange-300";
      case "table": return "bg-green-100 border-green-300";
      case "fields": return "bg-purple-100 border-purple-300";
      default: return "bg-gray-100 border-gray-300";
    }
  };

  const getRowTypeLabel = (type: CardContentRowConfig["type"]) => {
    switch (type) {
      case "header": return "헤더";
      case "aggregation": return "집계";
      case "table": return "테이블";
      case "fields": return "필드";
      default: return type;
    }
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-[95vw] sm:max-w-[900px] max-h-[90vh] flex flex-col p-0">
        <DialogHeader className="px-4 pt-4 pb-2 border-b shrink-0">
          <DialogTitle className="text-base">레이아웃 설정</DialogTitle>
          <DialogDescription className="text-xs">
            카드 내부의 행(헤더, 집계, 테이블, 필드)을 구성합니다. 각 행은 순서를 변경할 수 있습니다.
          </DialogDescription>
        </DialogHeader>

        <div className="flex-1 overflow-hidden px-4">
          <ScrollArea className="h-[calc(90vh-180px)]">
            <div className="space-y-3 py-3 pr-3">
              {/* 행 추가 버튼 */}
              <div className="flex gap-2 sticky top-0 bg-background z-10 pb-2 border-b">
                <Button size="sm" variant="outline" onClick={() => addRow("header")} className="h-8 text-xs flex-1 bg-blue-50 hover:bg-blue-100 border-blue-200">
                  <Plus className="h-3 w-3 mr-1" />
                  헤더
                </Button>
                <Button size="sm" variant="outline" onClick={() => addRow("aggregation")} className="h-8 text-xs flex-1 bg-orange-50 hover:bg-orange-100 border-orange-200">
                  <Plus className="h-3 w-3 mr-1" />
                  집계
                </Button>
                <Button size="sm" variant="outline" onClick={() => addRow("table")} className="h-8 text-xs flex-1 bg-green-50 hover:bg-green-100 border-green-200">
                  <Plus className="h-3 w-3 mr-1" />
                  테이블
                </Button>
                <Button size="sm" variant="outline" onClick={() => addRow("fields")} className="h-8 text-xs flex-1 bg-purple-50 hover:bg-purple-100 border-purple-200">
                  <Plus className="h-3 w-3 mr-1" />
                  필드
                </Button>
              </div>

              {/* 행 목록 */}
              {localRows.length === 0 ? (
                <div className="text-center py-8 border border-dashed rounded-lg">
                  <p className="text-sm text-muted-foreground mb-2">레이아웃 행이 없습니다</p>
                  <p className="text-xs text-muted-foreground">
                    위의 버튼으로 헤더, 집계, 테이블, 필드 행을 추가하세요
                  </p>
                </div>
              ) : (
                <div className="space-y-3">
                  {localRows.map((row, index) => (
                    <LayoutRowConfigModal
                      key={row.id}
                      row={row}
                      rowIndex={index}
                      totalRows={localRows.length}
                      allTables={allTables}
                      dataSourceTable={dataSourceTable}
                      aggregations={aggregations}
                      onUpdateRow={(updates) => updateRow(index, updates)}
                      onRemoveRow={() => removeRow(index)}
                      onMoveRow={(direction) => moveRow(index, direction)}
                      onAddColumn={() => addColumn(index)}
                      onRemoveColumn={(colIndex) => removeColumn(index, colIndex)}
                      onUpdateColumn={(colIndex, updates) => updateColumn(index, colIndex, updates)}
                      onAddAggField={() => addAggField(index)}
                      onRemoveAggField={(fieldIndex) => removeAggField(index, fieldIndex)}
                      onUpdateAggField={(fieldIndex, updates) => updateAggField(index, fieldIndex, updates)}
                      onMoveAggField={(fieldIndex, direction) => moveAggField(index, fieldIndex, direction)}
                      onAddTableColumn={() => addTableColumn(index)}
                      onRemoveTableColumn={(colIndex) => removeTableColumn(index, colIndex)}
                      onUpdateTableColumn={(colIndex, updates) => updateTableColumn(index, colIndex, updates)}
                      onMoveTableColumn={(colIndex, direction) => moveTableColumn(index, colIndex, direction)}
                      getRowTypeColor={getRowTypeColor}
                      getRowTypeLabel={getRowTypeLabel}
                    />
                  ))}
                </div>
              )}
            </div>
          </ScrollArea>
        </div>

        <DialogFooter className="px-4 py-3 border-t shrink-0">
          <Button variant="outline" onClick={() => onOpenChange(false)} className="h-9 text-sm">
            취소
          </Button>
          <Button onClick={handleSave} className="h-9 text-sm">
            저장 ({localRows.length}개 행)
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

// 레이아웃 행 설정 (모달용)
function LayoutRowConfigModal({
  row,
  rowIndex,
  totalRows,
  allTables,
  dataSourceTable,
  aggregations,
  onUpdateRow,
  onRemoveRow,
  onMoveRow,
  onAddColumn,
  onRemoveColumn,
  onUpdateColumn,
  onAddAggField,
  onRemoveAggField,
  onUpdateAggField,
  onMoveAggField,
  onAddTableColumn,
  onRemoveTableColumn,
  onUpdateTableColumn,
  onMoveTableColumn,
  getRowTypeColor,
  getRowTypeLabel,
}: {
  row: CardContentRowConfig;
  rowIndex: number;
  totalRows: number;
  allTables: { tableName: string; displayName?: string }[];
  dataSourceTable: string;
  aggregations: AggregationConfig[];
  onUpdateRow: (updates: Partial<CardContentRowConfig>) => void;
  onRemoveRow: () => void;
  onMoveRow: (direction: "up" | "down") => void;
  onAddColumn: () => void;
  onRemoveColumn: (colIndex: number) => void;
  onUpdateColumn: (colIndex: number, updates: Partial<CardColumnConfig>) => void;
  onAddAggField: () => void;
  onRemoveAggField: (fieldIndex: number) => void;
  onUpdateAggField: (fieldIndex: number, updates: Partial<AggregationDisplayConfig>) => void;
  onMoveAggField: (fieldIndex: number, direction: "up" | "down") => void;
  onAddTableColumn: () => void;
  onRemoveTableColumn: (colIndex: number) => void;
  onUpdateTableColumn: (colIndex: number, updates: Partial<TableColumnConfig>) => void;
  onMoveTableColumn: (colIndex: number, direction: "up" | "down") => void;
  getRowTypeColor: (type: CardContentRowConfig["type"]) => string;
  getRowTypeLabel: (type: CardContentRowConfig["type"]) => string;
}) {
  const [isExpanded, setIsExpanded] = useState(true);

  return (
    <div className={cn("border rounded-lg overflow-hidden", getRowTypeColor(row.type))}>
      {/* 행 헤더 */}
      <div className="flex items-center justify-between p-3 bg-white/50">
        <div className="flex items-center gap-2">
          {/* 순서 변경 버튼 */}
          <div className="flex flex-col">
            <Button
              size="sm"
              variant="ghost"
              onClick={() => onMoveRow("up")}
              disabled={rowIndex === 0}
              className="h-4 w-6 p-0"
            >
              <ChevronUp className="h-3 w-3" />
            </Button>
            <Button
              size="sm"
              variant="ghost"
              onClick={() => onMoveRow("down")}
              disabled={rowIndex === totalRows - 1}
              className="h-4 w-6 p-0"
            >
              <ChevronDown className="h-3 w-3" />
            </Button>
          </div>
          <Badge className="text-xs">{getRowTypeLabel(row.type)} {rowIndex + 1}</Badge>
          <span className="text-xs text-muted-foreground">
            {row.type === "header" || row.type === "fields" 
              ? `${(row.columns || []).length}개 컬럼`
              : row.type === "aggregation"
              ? `${(row.aggregationFields || []).length}개 필드`
              : row.type === "table"
              ? `${(row.tableColumns || []).length}개 컬럼`
              : ""}
          </span>
        </div>
        <div className="flex items-center gap-1">
          <Button
            size="sm"
            variant="ghost"
            onClick={() => setIsExpanded(!isExpanded)}
            className="h-7 px-2 text-xs"
          >
            {isExpanded ? "접기" : "펼치기"}
          </Button>
          <Button
            size="sm"
            variant="ghost"
            onClick={onRemoveRow}
            className="h-7 w-7 p-0 hover:bg-destructive/10 hover:text-destructive"
          >
            <X className="h-4 w-4" />
          </Button>
        </div>
      </div>

      {/* 행 내용 */}
      {isExpanded && (
        <div className="p-4 bg-white space-y-4">
          {/* 헤더/필드 타입 */}
          {(row.type === "header" || row.type === "fields") && (
            <div className="space-y-3">
              <div className="grid grid-cols-3 gap-3">
                <div className="space-y-1">
                  <Label className="text-xs">레이아웃</Label>
                  <Select
                    value={row.layout || "horizontal"}
                    onValueChange={(value) => onUpdateRow({ layout: value as "horizontal" | "vertical" })}
                  >
                    <SelectTrigger className="h-8 text-xs">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="horizontal">가로</SelectItem>
                      <SelectItem value="vertical">세로</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
                <div className="space-y-1">
                  <Label className="text-xs">배경색</Label>
                  <Select
                    value={row.backgroundColor || "none"}
                    onValueChange={(value) => onUpdateRow({ backgroundColor: value === "none" ? undefined : value })}
                  >
                    <SelectTrigger className="h-8 text-xs">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="none">없음</SelectItem>
                      <SelectItem value="blue">파랑</SelectItem>
                      <SelectItem value="green">초록</SelectItem>
                      <SelectItem value="orange">주황</SelectItem>
                      <SelectItem value="gray">회색</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
                <div className="space-y-1">
                  <Label className="text-xs">간격</Label>
                  <Input
                    value={row.gap || "16px"}
                    onChange={(e) => onUpdateRow({ gap: e.target.value })}
                    placeholder="16px"
                    className="h-8 text-xs"
                  />
                </div>
              </div>

              {/* 컬럼 목록 */}
              <div className="space-y-2">
                <div className="flex items-center justify-between">
                  <Label className="text-xs font-semibold">컬럼 ({(row.columns || []).length}개)</Label>
                  <Button size="sm" variant="outline" onClick={onAddColumn} className="h-7 text-xs">
                    <Plus className="h-3 w-3 mr-1" />
                    컬럼 추가
                  </Button>
                </div>
                {(row.columns || []).map((col, colIndex) => (
                  <div key={col.id} className="border rounded p-3 space-y-2 bg-gray-50">
                    <div className="flex items-center justify-between">
                      <span className="text-xs font-medium">컬럼 {colIndex + 1}</span>
                      <Button size="sm" variant="ghost" onClick={() => onRemoveColumn(colIndex)} className="h-6 w-6 p-0">
                        <X className="h-3 w-3" />
                      </Button>
                    </div>
                    <div className="grid grid-cols-4 gap-2">
                      <div className="space-y-1">
                        <Label className="text-[10px]">필드</Label>
                        <SourceColumnSelector
                          sourceTable={dataSourceTable}
                          value={col.field}
                          onChange={(value) => onUpdateColumn(colIndex, { field: value })}
                          placeholder="필드 선택"
                        />
                      </div>
                      <div className="space-y-1">
                        <Label className="text-[10px]">라벨</Label>
                        <Input
                          value={col.label}
                          onChange={(e) => onUpdateColumn(colIndex, { label: e.target.value })}
                          placeholder="라벨"
                          className="h-6 text-[10px]"
                        />
                      </div>
                      <div className="space-y-1">
                        <Label className="text-[10px]">타입</Label>
                        <Select
                          value={col.type || "text"}
                          onValueChange={(value) => onUpdateColumn(colIndex, { type: value as CardColumnConfig["type"] })}
                        >
                          <SelectTrigger className="h-6 text-[10px]">
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            <SelectItem value="text">텍스트</SelectItem>
                            <SelectItem value="number">숫자</SelectItem>
                            <SelectItem value="date">날짜</SelectItem>
                            <SelectItem value="select">선택</SelectItem>
                          </SelectContent>
                        </Select>
                      </div>
                      <div className="space-y-1">
                        <Label className="text-[10px]">너비</Label>
                        <Input
                          value={col.width || "auto"}
                          onChange={(e) => onUpdateColumn(colIndex, { width: e.target.value })}
                          placeholder="auto"
                          className="h-6 text-[10px]"
                        />
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          )}

          {/* 집계 타입 */}
          {row.type === "aggregation" && (
            <div className="space-y-3">
              <div className="grid grid-cols-2 gap-3">
                <div className="space-y-1">
                  <Label className="text-xs">레이아웃</Label>
                  <Select
                    value={row.aggregationLayout || "horizontal"}
                    onValueChange={(value) => onUpdateRow({ aggregationLayout: value as "horizontal" | "grid" })}
                  >
                    <SelectTrigger className="h-8 text-xs">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="horizontal">가로 나열</SelectItem>
                      <SelectItem value="grid">그리드</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
                {row.aggregationLayout === "grid" && (
                  <div className="space-y-1">
                    <Label className="text-xs">컬럼 수</Label>
                    <Select
                      value={String(row.aggregationColumns || 4)}
                      onValueChange={(value) => onUpdateRow({ aggregationColumns: parseInt(value) })}
                    >
                      <SelectTrigger className="h-8 text-xs">
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="2">2개</SelectItem>
                        <SelectItem value="3">3개</SelectItem>
                        <SelectItem value="4">4개</SelectItem>
                        <SelectItem value="5">5개</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>
                )}
              </div>

              {/* 집계 필드 목록 */}
              <div className="space-y-2">
                <div className="flex items-center justify-between">
                  <Label className="text-xs font-semibold">집계 필드 ({(row.aggregationFields || []).length}개)</Label>
                  <Button size="sm" variant="outline" onClick={onAddAggField} className="h-7 text-xs">
                    <Plus className="h-3 w-3 mr-1" />
                    필드 추가
                  </Button>
                </div>
                {aggregations.filter(a => !a.hidden).length === 0 && (
                  <p className="text-xs text-amber-600 bg-amber-50 p-2 rounded">
                    그룹 탭에서 먼저 집계를 설정해주세요
                  </p>
                )}
                {(row.aggregationFields || []).map((field, fieldIndex) => (
                  <div key={fieldIndex} className="border rounded p-3 space-y-2 bg-gray-50">
                    <div className="flex items-center justify-between">
                      <div className="flex items-center gap-1">
                        <Button
                          size="sm"
                          variant="ghost"
                          onClick={() => onMoveAggField(fieldIndex, "up")}
                          disabled={fieldIndex === 0}
                          className="h-5 w-5 p-0"
                        >
                          <ChevronUp className="h-3 w-3" />
                        </Button>
                        <Button
                          size="sm"
                          variant="ghost"
                          onClick={() => onMoveAggField(fieldIndex, "down")}
                          disabled={fieldIndex === (row.aggregationFields?.length || 0) - 1}
                          className="h-5 w-5 p-0"
                        >
                          <ChevronDown className="h-3 w-3" />
                        </Button>
                        <span className="text-xs font-medium">집계 {fieldIndex + 1}</span>
                      </div>
                      <Button size="sm" variant="ghost" onClick={() => onRemoveAggField(fieldIndex)} className="h-6 w-6 p-0">
                        <X className="h-3 w-3" />
                      </Button>
                    </div>
                    <div className="grid grid-cols-4 gap-2">
                      <div className="space-y-1">
                        <Label className="text-[10px]">집계 필드</Label>
                        <Select
                          value={field.aggregationResultField}
                          onValueChange={(value) => onUpdateAggField(fieldIndex, { aggregationResultField: value })}
                        >
                          <SelectTrigger className="h-6 text-[10px]">
                            <SelectValue placeholder="선택" />
                          </SelectTrigger>
                          <SelectContent>
                            {aggregations.filter(agg => !agg.hidden).map((agg) => (
                              <SelectItem key={agg.resultField} value={agg.resultField}>
                                {agg.label || agg.resultField}
                              </SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                      </div>
                      <div className="space-y-1">
                        <Label className="text-[10px]">표시 라벨</Label>
                        <Input
                          value={field.label}
                          onChange={(e) => onUpdateAggField(fieldIndex, { label: e.target.value })}
                          placeholder="라벨"
                          className="h-6 text-[10px]"
                        />
                      </div>
                      <div className="space-y-1">
                        <Label className="text-[10px]">배경색</Label>
                        <Select
                          value={field.backgroundColor || "none"}
                          onValueChange={(value) => onUpdateAggField(fieldIndex, { backgroundColor: value === "none" ? undefined : value })}
                        >
                          <SelectTrigger className="h-6 text-[10px]">
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            <SelectItem value="none">없음</SelectItem>
                            <SelectItem value="blue">파랑</SelectItem>
                            <SelectItem value="green">초록</SelectItem>
                            <SelectItem value="orange">주황</SelectItem>
                          </SelectContent>
                        </Select>
                      </div>
                      <div className="space-y-1">
                        <Label className="text-[10px]">폰트 크기</Label>
                        <Select
                          value={field.fontSize || "base"}
                          onValueChange={(value) => onUpdateAggField(fieldIndex, { fontSize: value as AggregationDisplayConfig["fontSize"] })}
                        >
                          <SelectTrigger className="h-6 text-[10px]">
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            <SelectItem value="sm">작게</SelectItem>
                            <SelectItem value="base">보통</SelectItem>
                            <SelectItem value="lg">크게</SelectItem>
                            <SelectItem value="xl">매우 크게</SelectItem>
                          </SelectContent>
                        </Select>
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          )}

          {/* 테이블 타입 */}
          {row.type === "table" && (
            <div className="space-y-3">
              <div className="grid grid-cols-3 gap-3">
                <div className="space-y-1">
                  <Label className="text-xs">테이블 제목</Label>
                  <Input
                    value={row.tableTitle || ""}
                    onChange={(e) => onUpdateRow({ tableTitle: e.target.value })}
                    placeholder="테이블 제목"
                    className="h-8 text-xs"
                  />
                </div>
                <div className="space-y-1">
                  <Label className="text-xs">헤더 표시</Label>
                  <div className="flex items-center h-8 px-3 border rounded-md bg-background">
                    <Switch
                      checked={row.showTableHeader !== false}
                      onCheckedChange={(checked) => onUpdateRow({ showTableHeader: checked })}
                      className="scale-90"
                    />
                    <span className="ml-2 text-xs">{row.showTableHeader !== false ? "표시" : "숨김"}</span>
                  </div>
                </div>
                <div className="space-y-1">
                  <Label className="text-xs">최대 높이</Label>
                  <Input
                    value={row.tableMaxHeight || ""}
                    onChange={(e) => onUpdateRow({ tableMaxHeight: e.target.value })}
                    placeholder="예: 300px"
                    className="h-8 text-xs"
                  />
                </div>
              </div>

              {/* 외부 데이터 소스 설정 */}
              <div className="border rounded p-3 bg-blue-50 space-y-3">
                <div className="flex items-center justify-between">
                  <Label className="text-xs font-semibold">외부 데이터 소스</Label>
                  <Switch
                    checked={row.tableDataSource?.enabled || false}
                    onCheckedChange={(checked) => onUpdateRow({
                      tableDataSource: { ...row.tableDataSource, enabled: checked, sourceTable: "", joinConditions: [] }
                    })}
                    className="scale-90"
                  />
                </div>
                {row.tableDataSource?.enabled && (
                  <>
                    <div className="space-y-1">
                      <Label className="text-[10px]">소스 테이블</Label>
                      <TableSelector
                        value={row.tableDataSource?.sourceTable || ""}
                        onChange={(value) => onUpdateRow({
                          tableDataSource: { ...row.tableDataSource!, sourceTable: value }
                        })}
                      />
                    </div>

                    {/* 조인 조건 설정 */}
                    <div className="space-y-2 pt-2 border-t border-blue-200">
                      <div className="space-y-1">
                        <Label className="text-[10px] font-semibold">조인 조건</Label>
                        <p className="text-[9px] text-muted-foreground">
                          두 테이블을 연결하는 키를 설정합니다
                        </p>
                      </div>
                      {(row.tableDataSource?.joinConditions || []).map((condition, conditionIndex) => (
                        <div key={`join-${conditionIndex}`} className="space-y-2 p-2 border rounded bg-white">
                          <div className="flex items-center justify-between">
                            <span className="text-[9px] font-medium">조인 {conditionIndex + 1}</span>
                            <Button
                              size="sm"
                              variant="ghost"
                              onClick={() => {
                                const newConditions = [...(row.tableDataSource?.joinConditions || [])];
                                newConditions.splice(conditionIndex, 1);
                                onUpdateRow({
                                  tableDataSource: { ...row.tableDataSource!, joinConditions: newConditions }
                                });
                              }}
                              className="h-5 w-5 p-0"
                            >
                              <X className="h-3 w-3" />
                            </Button>
                          </div>

                          <div className="grid grid-cols-2 gap-2">
                            <div className="space-y-1">
                              <Label className="text-[9px]">조인 키 (소스)</Label>
                              <SourceColumnSelector
                                sourceTable={row.tableDataSource?.sourceTable || ""}
                                value={condition.sourceKey}
                                onChange={(value) => {
                                  const newConditions = [...(row.tableDataSource?.joinConditions || [])];
                                  newConditions[conditionIndex] = { ...condition, sourceKey: value };
                                  onUpdateRow({
                                    tableDataSource: { ...row.tableDataSource!, joinConditions: newConditions }
                                  });
                                }}
                                placeholder="예: sales_order_id"
                              />
                              <p className="text-[8px] text-muted-foreground">
                                외부 테이블의 컬럼
                              </p>
                            </div>

                            <div className="space-y-1">
                              <Label className="text-[9px]">조인 키 (대상)</Label>
                              <SourceColumnSelector
                                sourceTable={dataSourceTable || ""}
                                value={condition.referenceKey}
                                onChange={(value) => {
                                  const newConditions = [...(row.tableDataSource?.joinConditions || [])];
                                  newConditions[conditionIndex] = { ...condition, referenceKey: value };
                                  onUpdateRow({
                                    tableDataSource: { ...row.tableDataSource!, joinConditions: newConditions }
                                  });
                                }}
                                placeholder="예: id"
                              />
                              <p className="text-[8px] text-muted-foreground">
                                메인 테이블의 컬럼
                              </p>
                            </div>
                          </div>

                          <div className="mt-1 p-1.5 bg-blue-50 rounded border border-blue-100">
                            <p className="text-[8px] text-blue-700 font-mono">
                              {row.tableDataSource?.sourceTable}.{condition.sourceKey} = {dataSourceTable}.{condition.referenceKey}
                            </p>
                            <p className="text-[8px] text-muted-foreground mt-0.5">
                              외부 테이블에서 메인 테이블의 값과 일치하는 데이터를 가져옵니다
                            </p>
                          </div>
                        </div>
                      ))}

                      <Button
                        size="sm"
                        variant="outline"
                        onClick={() => {
                          const newConditions = [
                            ...(row.tableDataSource?.joinConditions || []),
                            { sourceKey: "", referenceKey: "", referenceType: "card" as const },
                          ];
                          onUpdateRow({
                            tableDataSource: { ...row.tableDataSource!, joinConditions: newConditions }
                          });
                        }}
                        className="w-full h-7 text-[9px]"
                      >
                        <Plus className="h-3 w-3 mr-1" />
                        조인 조건 추가
                      </Button>
                    </div>

                    {/* 필터 설정 */}
                    <div className="space-y-2 pt-2 border-t border-blue-200">
                      <div className="flex items-center justify-between">
                        <div className="space-y-1">
                          <Label className="text-[10px] font-semibold">데이터 필터</Label>
                          <p className="text-[9px] text-muted-foreground">
                            특정 조건으로 데이터를 제외합니다
                          </p>
                        </div>
                        <Switch
                          checked={row.tableDataSource?.filterConfig?.enabled || false}
                          onCheckedChange={(checked) => {
                            onUpdateRow({
                              tableDataSource: {
                                ...row.tableDataSource!,
                                filterConfig: {
                                  enabled: checked,
                                  filterField: "",
                                  filterType: "notEquals",
                                  referenceField: "",
                                  referenceSource: "representativeData",
                                },
                              },
                            });
                          }}
                          className="scale-75"
                        />
                      </div>

                      {row.tableDataSource?.filterConfig?.enabled && (
                        <div className="space-y-2 p-2 bg-amber-50 rounded border border-amber-200">
                          <div className="grid grid-cols-2 gap-2">
                            <div className="space-y-1">
                              <Label className="text-[9px]">필터 필드</Label>
                              <SourceColumnSelector
                                sourceTable={row.tableDataSource?.sourceTable || ""}
                                value={row.tableDataSource?.filterConfig?.filterField || ""}
                                onChange={(value) => {
                                  onUpdateRow({
                                    tableDataSource: {
                                      ...row.tableDataSource!,
                                      filterConfig: {
                                        ...row.tableDataSource!.filterConfig!,
                                        filterField: value,
                                      },
                                    },
                                  });
                                }}
                                placeholder="예: order_no"
                              />
                              <p className="text-[8px] text-muted-foreground">
                                외부 테이블에서 비교할 컬럼
                              </p>
                            </div>

                            <div className="space-y-1">
                              <Label className="text-[9px]">비교 필드</Label>
                              <SourceColumnSelector
                                sourceTable={dataSourceTable || ""}
                                value={row.tableDataSource?.filterConfig?.referenceField || ""}
                                onChange={(value) => {
                                  onUpdateRow({
                                    tableDataSource: {
                                      ...row.tableDataSource!,
                                      filterConfig: {
                                        ...row.tableDataSource!.filterConfig!,
                                        referenceField: value,
                                      },
                                    },
                                  });
                                }}
                                placeholder="예: order_no"
                              />
                              <p className="text-[8px] text-muted-foreground">
                                현재 선택한 행의 컬럼
                              </p>
                            </div>
                          </div>

                          <div className="space-y-1">
                            <Label className="text-[9px]">필터 조건</Label>
                            <Select
                              value={row.tableDataSource?.filterConfig?.filterType || "notEquals"}
                              onValueChange={(value: "equals" | "notEquals") => {
                                onUpdateRow({
                                  tableDataSource: {
                                    ...row.tableDataSource!,
                                    filterConfig: {
                                      ...row.tableDataSource!.filterConfig!,
                                      filterType: value,
                                    },
                                  },
                                });
                              }}
                            >
                              <SelectTrigger className="h-7 text-[10px]">
                                <SelectValue />
                              </SelectTrigger>
                              <SelectContent>
                                <SelectItem value="notEquals">같지 않은 값만 (내꺼 제외)</SelectItem>
                                <SelectItem value="equals">같은 값만 (내꺼만)</SelectItem>
                              </SelectContent>
                            </Select>
                          </div>

                          <div className="mt-2 p-1.5 bg-amber-100 rounded border border-amber-200">
                            <p className="text-[8px] text-amber-800 font-mono">
                              {row.tableDataSource?.sourceTable}.{row.tableDataSource?.filterConfig?.filterField} != 현재행.{row.tableDataSource?.filterConfig?.referenceField}
                            </p>
                            <p className="text-[8px] text-muted-foreground mt-0.5">
                              {row.tableDataSource?.filterConfig?.filterType === "notEquals"
                                ? "현재 선택한 행과 다른 데이터만 표시합니다"
                                : "현재 선택한 행과 같은 데이터만 표시합니다"}
                            </p>
                          </div>
                        </div>
                      )}
                    </div>
                  </>
                )}
              </div>

              {/* CRUD 설정 */}
              <div className="space-y-2 p-3 bg-green-100/50 dark:bg-green-900/20 rounded border border-green-200 dark:border-green-800">
                <Label className="text-xs font-semibold">CRUD 설정</Label>
                <div className="flex flex-wrap gap-4">
                  <div className="flex items-center gap-2">
                    <Switch
                      checked={row.tableCrud?.allowCreate || false}
                      onCheckedChange={(checked) =>
                        onUpdateRow({
                          tableCrud: { ...row.tableCrud, allowCreate: checked, allowUpdate: row.tableCrud?.allowUpdate || false, allowDelete: row.tableCrud?.allowDelete || false },
                        })
                      }
                      className="scale-90"
                    />
                    <Label className="text-xs">추가</Label>
                  </div>
                  <div className="flex items-center gap-2">
                    <Switch
                      checked={row.tableCrud?.allowUpdate || false}
                      onCheckedChange={(checked) =>
                        onUpdateRow({
                          tableCrud: { ...row.tableCrud, allowCreate: row.tableCrud?.allowCreate || false, allowUpdate: checked, allowDelete: row.tableCrud?.allowDelete || false },
                        })
                      }
                      className="scale-90"
                    />
                    <Label className="text-xs">수정</Label>
                  </div>
                  <div className="flex items-center gap-2">
                    <Switch
                      checked={row.tableCrud?.allowDelete || false}
                      onCheckedChange={(checked) =>
                        onUpdateRow({
                          tableCrud: { ...row.tableCrud, allowCreate: row.tableCrud?.allowCreate || false, allowUpdate: row.tableCrud?.allowUpdate || false, allowDelete: checked },
                        })
                      }
                      className="scale-90"
                    />
                    <Label className="text-xs">삭제</Label>
                  </div>
                </div>
                {row.tableCrud?.allowDelete && (
                  <div className="flex items-center gap-2 pl-2 pt-1 border-t border-green-200">
                    <Switch
                      checked={row.tableCrud?.deleteConfirm?.enabled !== false}
                      onCheckedChange={(checked) =>
                        onUpdateRow({
                          tableCrud: { ...row.tableCrud!, deleteConfirm: { enabled: checked } },
                        })
                      }
                      className="scale-75"
                    />
                    <Label className="text-[10px]">삭제 확인 팝업</Label>
                  </div>
                )}
              </div>

              {/* 🆕 v3.13: 행 추가 시 자동 채번 설정 */}
              {row.tableCrud?.allowCreate && (
                <RowNumberingConfigSection
                  row={row}
                  onUpdateRow={onUpdateRow}
                />
              )}

              {/* 🆕 v3.12: 연동 저장 설정 */}
              <SyncSaveConfigSection
                row={row}
                allTables={allTables}
                onUpdateRow={onUpdateRow}
              />

              {/* 테이블 컬럼 목록 */}
              <div className="space-y-2">
                <div className="flex items-center justify-between">
                  <Label className="text-xs font-semibold">테이블 컬럼 ({(row.tableColumns || []).length}개)</Label>
                  <Button size="sm" variant="outline" onClick={onAddTableColumn} className="h-7 text-xs">
                    <Plus className="h-3 w-3 mr-1" />
                    컬럼 추가
                  </Button>
                </div>
                {(row.tableColumns || []).map((col, colIndex) => (
                  <div key={col.id} className="border rounded p-3 space-y-2 bg-gray-50">
                    <div className="flex items-center justify-between">
                      <div className="flex items-center gap-1">
                        <Button
                          size="sm"
                          variant="ghost"
                          onClick={() => onMoveTableColumn(colIndex, "up")}
                          disabled={colIndex === 0}
                          className="h-5 w-5 p-0"
                        >
                          <ChevronUp className="h-3 w-3" />
                        </Button>
                        <Button
                          size="sm"
                          variant="ghost"
                          onClick={() => onMoveTableColumn(colIndex, "down")}
                          disabled={colIndex === (row.tableColumns?.length || 0) - 1}
                          className="h-5 w-5 p-0"
                        >
                          <ChevronDown className="h-3 w-3" />
                        </Button>
                        <span className="text-xs font-medium">컬럼 {colIndex + 1}</span>
                      </div>
                      <Button size="sm" variant="ghost" onClick={() => onRemoveTableColumn(colIndex)} className="h-6 w-6 p-0">
                        <X className="h-3 w-3" />
                      </Button>
                    </div>
                    <div className="grid grid-cols-5 gap-2">
                      <div className="space-y-1">
                        <Label className="text-[10px]">필드</Label>
                        <SourceColumnSelector
                          sourceTable={row.tableDataSource?.enabled ? row.tableDataSource.sourceTable : dataSourceTable}
                          value={col.field}
                          onChange={(value) => onUpdateTableColumn(colIndex, { field: value })}
                          placeholder="필드 선택"
                        />
                      </div>
                      <div className="space-y-1">
                        <Label className="text-[10px]">라벨</Label>
                        <Input
                          value={col.label}
                          onChange={(e) => onUpdateTableColumn(colIndex, { label: e.target.value })}
                          placeholder="라벨"
                          className="h-6 text-[10px]"
                        />
                      </div>
                      <div className="space-y-1">
                        <Label className="text-[10px]">타입</Label>
                        <Select
                          value={col.type || "text"}
                          onValueChange={(value) => onUpdateTableColumn(colIndex, { type: value as TableColumnConfig["type"] })}
                        >
                          <SelectTrigger className="h-6 text-[10px]">
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            <SelectItem value="text">텍스트</SelectItem>
                            <SelectItem value="number">숫자</SelectItem>
                            <SelectItem value="date">날짜</SelectItem>
                            <SelectItem value="select">선택</SelectItem>
                          </SelectContent>
                        </Select>
                      </div>
                      <div className="space-y-1">
                        <Label className="text-[10px]">수정 가능</Label>
                        <div className="flex items-center h-6 px-2 border rounded-md bg-background">
                          <Switch
                            checked={col.editable || false}
                            onCheckedChange={(checked) => onUpdateTableColumn(colIndex, { editable: checked })}
                            className="scale-75"
                          />
                          <span className="ml-1 text-[10px]">{col.editable ? "예" : "아니오"}</span>
                        </div>
                      </div>
                      <div className="space-y-1">
                        <Label className="text-[10px]">숨김</Label>
                        <div className="flex items-center h-6 px-2 border rounded-md bg-background">
                          <Switch
                            checked={col.hidden || false}
                            onCheckedChange={(checked) => onUpdateTableColumn(colIndex, { hidden: checked })}
                            className="scale-75"
                          />
                          <span className="ml-1 text-[10px]">{col.hidden ? "예" : "아니오"}</span>
                        </div>
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// 집계 설정 아이템 (로컬 상태 관리로 입력 시 리렌더링 방지)
// 🆕 v3.2: 다중 테이블 및 가상 집계(formula) 지원
function AggregationConfigItem({
  agg,
  index,
  sourceTable,
  allTables,
  existingAggregations,
  onUpdate,
  onRemove,
}: {
  agg: AggregationConfig;
  index: number;
  sourceTable: string;
  allTables: { tableName: string; displayName?: string }[];
  existingAggregations: AggregationConfig[]; // 연산식에서 참조할 수 있는 기존 집계들
  onUpdate: (updates: Partial<AggregationConfig>) => void;
  onRemove: () => void;
}) {
  const [localLabel, setLocalLabel] = useState(agg.label || "");
  const [localResultField, setLocalResultField] = useState(agg.resultField || "");
  const [localFormula, setLocalFormula] = useState(agg.formula || "");

  // agg 변경 시 로컬 상태 동기화
  useEffect(() => {
    setLocalLabel(agg.label || "");
    setLocalResultField(agg.resultField || "");
    setLocalFormula(agg.formula || "");
  }, [agg.label, agg.resultField, agg.formula]);

  // 현재 집계보다 앞에 정의된 집계들만 참조 가능 (순환 참조 방지)
  const referenceableAggregations = existingAggregations.slice(0, index);

  // sourceType 기본값 처리
  const currentSourceType = agg.sourceType || "column";

  return (
    <div className="border rounded p-2 space-y-1.5 bg-background min-w-0">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-1 min-w-0">
          <Badge 
            variant={currentSourceType === "formula" ? "default" : "secondary"} 
            className={cn(
              "text-[9px] px-1 py-0 shrink-0",
              currentSourceType === "formula" && "bg-purple-100 text-purple-700"
            )}
          >
            {currentSourceType === "formula" ? "가상" : "집계"} {index + 1}
          </Badge>
        </div>
        <Button
          size="sm"
          variant="ghost"
          onClick={onRemove}
          className="h-5 w-5 p-0 shrink-0"
        >
          <X className="h-3 w-3" />
        </Button>
      </div>

      {/* 집계 타입 선택 */}
      <div className="space-y-1 min-w-0">
        <Label className="text-[9px]">집계 타입</Label>
        <Select
          value={currentSourceType}
          onValueChange={(value) => onUpdate({ sourceType: value as "column" | "formula" })}
        >
          <SelectTrigger className="h-6 text-[10px] w-full min-w-0">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="column">컬럼 집계 (SUM, COUNT 등)</SelectItem>
            <SelectItem value="formula">가상 집계 (연산식)</SelectItem>
          </SelectContent>
        </Select>
      </div>

      {/* === 컬럼 집계 설정 === */}
      {currentSourceType === "column" && (
        <>
          {/* 테이블 선택 */}
          <div className="space-y-1 min-w-0">
            <Label className="text-[9px]">테이블</Label>
            <Select
              value={agg.sourceTable || sourceTable || ""}
              onValueChange={(value) => onUpdate({ sourceTable: value, sourceField: "" })}
            >
              <SelectTrigger className="h-6 text-[10px] w-full min-w-0">
                <SelectValue placeholder="테이블 선택" />
              </SelectTrigger>
              <SelectContent>
                {/* 기본 테이블 (dataSource) */}
                {sourceTable && (
                  <SelectItem value={sourceTable} className="text-[10px]">
                    {sourceTable} (기본)
                  </SelectItem>
                )}
                {/* 외부 테이블들 */}
                {allTables
                  .filter((t) => t.tableName !== sourceTable)
                  .map((t) => (
                    <SelectItem key={t.tableName} value={t.tableName} className="text-[10px]">
                      {t.displayName || t.tableName}
                    </SelectItem>
                  ))}
              </SelectContent>
            </Select>
            <p className="text-[8px] text-muted-foreground">
              기본 테이블 외 다른 테이블도 선택 가능
            </p>
          </div>

          {/* 컬럼 선택 */}
          <div className="space-y-1 min-w-0">
            <Label className="text-[9px]">원본 필드</Label>
            <SourceColumnSelector
              sourceTable={agg.sourceTable || sourceTable}
              value={agg.sourceField || ""}
              onChange={(value) => onUpdate({ sourceField: value })}
              placeholder="합계할 필드"
            />
          </div>

          {/* 집계 함수 */}
          <div className="space-y-1 min-w-0">
            <Label className="text-[9px]">집계 함수</Label>
            <Select
              value={agg.type || "sum"}
              onValueChange={(value) => onUpdate({ type: value as AggregationConfig["type"] })}
            >
              <SelectTrigger className="h-6 text-[10px] w-full min-w-0">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="sum">합계 (SUM)</SelectItem>
                <SelectItem value="count">개수 (COUNT)</SelectItem>
                <SelectItem value="avg">평균 (AVG)</SelectItem>
                <SelectItem value="min">최소 (MIN)</SelectItem>
                <SelectItem value="max">최대 (MAX)</SelectItem>
              </SelectContent>
            </Select>
          </div>
        </>
      )}

      {/* === 가상 집계 (연산식) 설정 === */}
      {currentSourceType === "formula" && (
        <FormulaBuilder
          formula={localFormula}
          sourceTable={sourceTable}
          allTables={allTables}
          referenceableAggregations={referenceableAggregations}
          onChange={(newFormula) => {
            setLocalFormula(newFormula);
            onUpdate({ formula: newFormula });
          }}
        />
      )}

      {/* 공통: 라벨 및 결과 필드명 */}
      <div className="flex gap-2 pt-1 border-t">
        <div className="flex-1 space-y-1 min-w-0">
          <Label className="text-[9px]">라벨</Label>
          <Input
            value={localLabel}
            onChange={(e) => setLocalLabel(e.target.value)}
            onBlur={() => onUpdate({ label: localLabel })}
            onKeyDown={(e) => {
              if (e.key === "Enter") {
                onUpdate({ label: localLabel });
              }
            }}
            placeholder="총수주잔량"
            className="h-6 text-[10px]"
          />
        </div>

        <div className="flex-1 space-y-1 min-w-0">
          <Label className="text-[9px]">결과 필드명</Label>
          <Input
            value={localResultField}
            onChange={(e) => setLocalResultField(e.target.value)}
            onBlur={() => onUpdate({ resultField: localResultField })}
            onKeyDown={(e) => {
              if (e.key === "Enter") {
                onUpdate({ resultField: localResultField });
              }
            }}
            placeholder="total_balance_qty"
            className="h-6 text-[10px] font-mono"
          />
        </div>
      </div>

      {/* 🆕 v3.9: 저장 설정 */}
      <AggregationSaveConfigSection
        agg={agg}
        sourceTable={sourceTable}
        allTables={allTables}
        onUpdate={onUpdate}
      />
    </div>
  );
}

// 🆕 v3.9: 집계 저장 설정 섹션
function AggregationSaveConfigSection({
  agg,
  sourceTable,
  allTables,
  onUpdate,
}: {
  agg: AggregationConfig;
  sourceTable: string;
  allTables: { tableName: string; displayName?: string }[];
  onUpdate: (updates: Partial<AggregationConfig>) => void;
}) {
  const saveConfig = agg.saveConfig || { enabled: false, autoSave: false, targetTable: "", targetColumn: "", joinKey: { sourceField: "", targetField: "" } };

  const updateSaveConfig = (updates: Partial<typeof saveConfig>) => {
    onUpdate({
      saveConfig: {
        ...saveConfig,
        ...updates,
      },
    });
  };

  return (
    <div className="space-y-2 pt-2 border-t border-dashed">
      <div className="flex items-center justify-between">
        <Label className="text-[9px] font-semibold">연관 테이블 저장</Label>
        <Switch
          checked={saveConfig.enabled}
          onCheckedChange={(checked) => updateSaveConfig({ enabled: checked })}
          className="scale-[0.6]"
        />
      </div>

      {saveConfig.enabled && (
        <div className="space-y-2 p-2 bg-blue-50/50 dark:bg-blue-900/20 rounded border border-blue-200 dark:border-blue-800">
          {/* 자동 저장 옵션 */}
          <div className="flex items-center justify-between">
            <div className="space-y-0.5">
              <Label className="text-[9px]">자동 저장</Label>
              <p className="text-[8px] text-muted-foreground">
                레이아웃에 없어도 저장
              </p>
            </div>
            <Switch
              checked={saveConfig.autoSave}
              onCheckedChange={(checked) => updateSaveConfig({ autoSave: checked })}
              className="scale-[0.6]"
            />
          </div>

          {/* 대상 테이블 */}
          <div className="space-y-1">
            <Label className="text-[9px]">대상 테이블</Label>
            <Select
              value={saveConfig.targetTable}
              onValueChange={(value) => {
                updateSaveConfig({ targetTable: value, targetColumn: "" });
              }}
            >
              <SelectTrigger className="h-6 text-[10px]">
                <SelectValue placeholder="테이블 선택" />
              </SelectTrigger>
              <SelectContent>
                {allTables.map((t) => (
                  <SelectItem key={t.tableName} value={t.tableName} className="text-[10px]">
                    {t.displayName || t.tableName}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          {/* 대상 컬럼 */}
          <div className="space-y-1">
            <Label className="text-[9px]">대상 컬럼</Label>
            <SourceColumnSelector
              sourceTable={saveConfig.targetTable}
              value={saveConfig.targetColumn}
              onChange={(value) => updateSaveConfig({ targetColumn: value })}
              placeholder="컬럼 선택"
            />
          </div>

          {/* 조인 키 설정 */}
          <div className="space-y-2">
            <Label className="text-[9px]">조인 키</Label>
            <div className="space-y-1.5">
              <div className="space-y-0.5">
                <span className="text-[8px] text-muted-foreground">카드 키 (현재 카드 데이터)</span>
                <SourceColumnSelector
                  sourceTable={sourceTable}
                  value={saveConfig.joinKey?.sourceField || ""}
                  onChange={(value) =>
                    updateSaveConfig({
                      joinKey: { ...saveConfig.joinKey, sourceField: value },
                    })
                  }
                  placeholder="카드 키 선택"
                />
              </div>
              <div className="flex justify-center">
                <span className="text-[10px] text-muted-foreground">↓</span>
              </div>
              <div className="space-y-0.5">
                <span className="text-[8px] text-muted-foreground">대상 키 (업데이트할 레코드 식별)</span>
                <SourceColumnSelector
                  sourceTable={saveConfig.targetTable}
                  value={saveConfig.joinKey?.targetField || ""}
                  onChange={(value) =>
                    updateSaveConfig({
                      joinKey: { ...saveConfig.joinKey, targetField: value },
                    })
                  }
                  placeholder="대상 키 선택"
                />
              </div>
            </div>
          </div>

          {/* 설정 요약 */}
          {saveConfig.targetTable && saveConfig.targetColumn && (
            <div className="p-1.5 bg-white/50 dark:bg-black/20 rounded text-[9px] space-y-1">
              <div>
                <span className="font-medium">저장 경로:</span>
                {saveConfig.autoSave && (
                  <Badge variant="secondary" className="ml-1 text-[8px] px-1 py-0">
                    자동
                  </Badge>
                )}
              </div>
              <div className="font-mono text-blue-600 dark:text-blue-400 break-all">
                {saveConfig.targetTable}.{saveConfig.targetColumn}
              </div>
              {saveConfig.joinKey?.sourceField && saveConfig.joinKey?.targetField && (
                <div className="text-[8px] text-muted-foreground">
                  조인: {saveConfig.joinKey.sourceField} → {saveConfig.joinKey.targetField}
                </div>
              )}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// 테이블 선택기 (Combobox) - 240px 최적화
function TableSelector({
  value,
  onChange,
  allTables,
  placeholder = "테이블 선택",
}: {
  value: string;
  onChange: (value: string) => void;
  allTables?: { tableName: string; displayName?: string }[];
  placeholder?: string;
}) {
  const [tables, setTables] = useState<{ tableName: string; displayName?: string }[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [open, setOpen] = useState(false);

  useEffect(() => {
    // allTables가 전달되면 API 호출 없이 사용
    if (allTables && allTables.length > 0) {
      setTables(allTables);
      return;
    }

    const loadTables = async () => {
      setIsLoading(true);
      try {
        const response = await tableManagementApi.getTableList();
        if (response.success && response.data) {
          // API 응답이 배열인 경우와 객체인 경우 모두 처리
          const tableData = Array.isArray(response.data)
            ? response.data
            : (response.data as any).tables || response.data || [];
          setTables(tableData);
        }
      } catch (error) {
        console.error("테이블 로드 실패:", error);
        setTables([]);
      } finally {
        setIsLoading(false);
      }
    };
    loadTables();
  }, [allTables]);

  const selectedTable = (tables || []).find((t) => t.tableName === value);
  const displayText = selectedTable ? selectedTable.tableName : placeholder;

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          variant="outline"
          role="combobox"
          aria-expanded={open}
          className="h-7 w-full justify-between text-[10px]"
          disabled={isLoading}
        >
          <span className="truncate">{isLoading ? "..." : displayText}</span>
          <ChevronsUpDown className="ml-1 h-3 w-3 shrink-0 opacity-50" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="p-0 max-h-[200px] w-[200px]" align="start">
        <Command>
          <CommandInput placeholder="검색..." className="text-[10px] h-7" />
          <CommandList className="max-h-[160px] overflow-y-auto">
            <CommandEmpty className="text-[10px] py-2">없음</CommandEmpty>
            <CommandGroup>
              {tables.map((table) => (
                <CommandItem
                  key={table.tableName}
                  value={`${table.tableName} ${table.displayName || ""}`}
                  onSelect={() => {
                    onChange(table.tableName);
                    setOpen(false);
                  }}
                  className="text-[10px] py-1"
                >
                  <Check
                    className={cn("mr-1 h-3 w-3", value === table.tableName ? "opacity-100" : "opacity-0")}
                  />
                  <span className="truncate">{table.tableName}</span>
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  );
}

// 모듈 레벨에서 탭 상태 유지 (컴포넌트 리마운트 시에도 유지)
let persistedActiveTab = "basic";

export function RepeatScreenModalConfigPanel({ config, onChange }: RepeatScreenModalConfigPanelProps) {
  const [localConfig, setLocalConfig] = useState<Partial<RepeatScreenModalProps>>(() => ({
    dataSource: { sourceTable: "" },
    saveMode: "all",
    cardSpacing: "24px",
    showCardBorder: true,
    showCardTitle: true,
    cardTitle: "카드 {index}",
    grouping: { enabled: false, groupByField: "", aggregations: [] },
    contentRows: [], // 🆕 v3: 자유 레이아웃
    // 레거시 호환
    cardMode: "simple",
    cardLayout: [],
    tableLayout: { headerRows: [], tableColumns: [] },
    ...config,
  }));

  const [allTables, setAllTables] = useState<{ tableName: string; displayName?: string }[]>([]);
  
  // 집계 설정 모달 상태
  const [aggregationModalOpen, setAggregationModalOpen] = useState(false);
  
  // 레이아웃 설정 모달 상태
  const [layoutModalOpen, setLayoutModalOpen] = useState(false);
  
  // 탭 상태 유지 (모듈 레벨 변수와 동기화)
  const [activeTab, setActiveTab] = useState(persistedActiveTab);
  
  // 탭 변경 시 모듈 레벨 변수도 업데이트
  const handleTabChange = (tab: string) => {
    persistedActiveTab = tab;
    setActiveTab(tab);
  };

  // 테이블 목록 로드
  useEffect(() => {
    const loadTables = async () => {
      try {
        const response = await tableManagementApi.getTableList();
        if (response.success && response.data) {
          // API 응답이 배열인 경우와 객체인 경우 모두 처리
          const tableData = Array.isArray(response.data) 
            ? response.data 
            : (response.data as any).tables || response.data || [];
          setAllTables(tableData);
        }
      } catch (error) {
        console.error("테이블 로드 실패:", error);
      }
    };
    loadTables();
  }, []);

  // Debounced update for input fields
  const updateConfigDebounced = useCallback(
    (updates: Partial<RepeatScreenModalProps>) => {
      const timeoutId = setTimeout(() => {
        setLocalConfig((prev) => {
          const newConfig = { ...prev, ...updates };
          onChange(newConfig);
          return newConfig;
        });
      }, 500);

      return () => clearTimeout(timeoutId);
    },
    [onChange]
  );

  // Immediate update for select/switch fields
  // requestAnimationFrame을 사용하여 React 렌더링 사이클 이후에 onChange 호출
  const updateConfig = useCallback((updates: Partial<RepeatScreenModalProps>) => {
    setLocalConfig((prev) => {
      const newConfig = { ...prev, ...updates };
      // 비동기로 onChange 호출하여 현재 렌더링 사이클 완료 후 실행
      requestAnimationFrame(() => {
        onChange(newConfig);
      });
      return newConfig;
    });
  }, [onChange]);

  // === 그룹핑 관련 함수 ===
  const updateGrouping = (updates: Partial<GroupingConfig>) => {
    updateConfig({
      grouping: {
        ...localConfig.grouping,
        enabled: localConfig.grouping?.enabled ?? false,
        groupByField: localConfig.grouping?.groupByField ?? "",
        aggregations: localConfig.grouping?.aggregations ?? [],
        ...updates,
      },
    });
  };

  const addAggregation = (sourceType: "column" | "formula" = "column") => {
    const newAgg: AggregationConfig = {
      sourceType,
      // column 타입 기본값
      ...(sourceType === "column" && {
        sourceTable: localConfig.dataSource?.sourceTable || "",
        sourceField: "",
        type: "sum" as const,
      }),
      // formula 타입 기본값
      ...(sourceType === "formula" && {
        formula: "",
      }),
      resultField: `agg_${Date.now()}`,
      label: "",
    };
    updateGrouping({
      aggregations: [...(localConfig.grouping?.aggregations || []), newAgg],
    });
  };

  const removeAggregation = (index: number) => {
    const newAggs = [...(localConfig.grouping?.aggregations || [])];
    newAggs.splice(index, 1);
    updateGrouping({ aggregations: newAggs });
  };

  const updateAggregation = (index: number, updates: Partial<AggregationConfig>) => {
    const newAggs = [...(localConfig.grouping?.aggregations || [])];
    newAggs[index] = { ...newAggs[index], ...updates };
    updateGrouping({ aggregations: newAggs });
  };

  // === 테이블 레이아웃 관련 함수 ===
  const updateTableLayout = (updates: Partial<TableLayoutConfig>) => {
    updateConfig({
      tableLayout: {
        ...localConfig.tableLayout,
        headerRows: localConfig.tableLayout?.headerRows ?? [],
        tableColumns: localConfig.tableLayout?.tableColumns ?? [],
        ...updates,
      },
    });
  };

  const addTableColumn = () => {
    const newCol: TableColumnConfig = {
      id: `tcol-${Date.now()}`,
      field: "",
      label: "",
      type: "text",
      width: "auto",
      editable: false,
    };
    updateTableLayout({
      tableColumns: [...(localConfig.tableLayout?.tableColumns || []), newCol],
    });
  };

  const removeTableColumn = (index: number) => {
    const newCols = [...(localConfig.tableLayout?.tableColumns || [])];
    newCols.splice(index, 1);
    updateTableLayout({ tableColumns: newCols });
  };

  const updateTableColumn = (index: number, updates: Partial<TableColumnConfig>) => {
    const newCols = [...(localConfig.tableLayout?.tableColumns || [])];
    newCols[index] = { ...newCols[index], ...updates };
    updateTableLayout({ tableColumns: newCols });
  };

  // === 헤더 행 관련 함수 (simple 모드와 동일) ===
  const addHeaderRow = () => {
    const newRow: CardRowConfig = {
      id: `hrow-${Date.now()}`,
      columns: [],
      gap: "16px",
      layout: "horizontal",
    };
    updateTableLayout({
      headerRows: [...(localConfig.tableLayout?.headerRows || []), newRow],
    });
  };

  const removeHeaderRow = (rowIndex: number) => {
    const newRows = [...(localConfig.tableLayout?.headerRows || [])];
    newRows.splice(rowIndex, 1);
    updateTableLayout({ headerRows: newRows });
  };

  const updateHeaderRow = (rowIndex: number, updates: Partial<CardRowConfig>) => {
    const newRows = [...(localConfig.tableLayout?.headerRows || [])];
    newRows[rowIndex] = { ...newRows[rowIndex], ...updates };
    updateTableLayout({ headerRows: newRows });
  };

  const addHeaderColumn = (rowIndex: number) => {
    const newRows = [...(localConfig.tableLayout?.headerRows || [])];
    const newColumn: CardColumnConfig = {
      id: `hcol-${Date.now()}`,
      field: "",
      label: "",
      type: "text",
      width: "auto",
      editable: false,
    };
    newRows[rowIndex].columns.push(newColumn);
    updateTableLayout({ headerRows: newRows });
  };

  const removeHeaderColumn = (rowIndex: number, colIndex: number) => {
    const newRows = [...(localConfig.tableLayout?.headerRows || [])];
    newRows[rowIndex].columns.splice(colIndex, 1);
    updateTableLayout({ headerRows: newRows });
  };

  const updateHeaderColumn = (rowIndex: number, colIndex: number, updates: Partial<CardColumnConfig>) => {
    const newRows = [...(localConfig.tableLayout?.headerRows || [])];
    newRows[rowIndex].columns[colIndex] = { ...newRows[rowIndex].columns[colIndex], ...updates };
    updateTableLayout({ headerRows: newRows });
  };

  // === 🆕 v3: contentRows 관련 함수 ===
  const addContentRow = (type: CardContentRowConfig["type"]) => {
    const newRow: CardContentRowConfig = {
      id: `crow-${Date.now()}`,
      type,
      // 타입별 기본값
      ...(type === "header" || type === "fields"
        ? { columns: [], layout: "horizontal", gap: "16px" }
        : {}),
      ...(type === "aggregation"
        ? { aggregationFields: [], aggregationLayout: "horizontal" }
        : {}),
      ...(type === "table"
        ? { tableColumns: [], showTableHeader: true }
        : {}),
    };
    updateConfig({
      contentRows: [...(localConfig.contentRows || []), newRow],
    });
  };

  const removeContentRow = (rowIndex: number) => {
    const newRows = [...(localConfig.contentRows || [])];
    newRows.splice(rowIndex, 1);
    updateConfig({ contentRows: newRows });
  };

  const updateContentRow = (rowIndex: number, updates: Partial<CardContentRowConfig>) => {
    const newRows = [...(localConfig.contentRows || [])];
    newRows[rowIndex] = { ...newRows[rowIndex], ...updates };
    updateConfig({ contentRows: newRows });
  };

  // contentRow 내 컬럼 관리 (header/fields 타입)
  const addContentRowColumn = (rowIndex: number) => {
    const newRows = [...(localConfig.contentRows || [])];
    const newColumn: CardColumnConfig = {
      id: `col-${Date.now()}`,
      field: "",
      label: "",
      type: "text",
      width: "auto",
      editable: false,
    };
    newRows[rowIndex].columns = [...(newRows[rowIndex].columns || []), newColumn];
    updateConfig({ contentRows: newRows });
  };

  const removeContentRowColumn = (rowIndex: number, colIndex: number) => {
    const newRows = [...(localConfig.contentRows || [])];
    newRows[rowIndex].columns?.splice(colIndex, 1);
    updateConfig({ contentRows: newRows });
  };

  const updateContentRowColumn = (rowIndex: number, colIndex: number, updates: Partial<CardColumnConfig>) => {
    const newRows = [...(localConfig.contentRows || [])];
    if (newRows[rowIndex].columns) {
      newRows[rowIndex].columns![colIndex] = { ...newRows[rowIndex].columns![colIndex], ...updates };
    }
    updateConfig({ contentRows: newRows });
  };

  // contentRow 내 집계 필드 관리 (aggregation 타입)
  const addContentRowAggField = (rowIndex: number) => {
    const newRows = [...(localConfig.contentRows || [])];
    const newAggField: AggregationDisplayConfig = {
      sourceType: "aggregation",
      aggregationResultField: "",
      label: "",
    };
    newRows[rowIndex].aggregationFields = [...(newRows[rowIndex].aggregationFields || []), newAggField];
    updateConfig({ contentRows: newRows });
  };

  const removeContentRowAggField = (rowIndex: number, fieldIndex: number) => {
    const newRows = [...(localConfig.contentRows || [])];
    newRows[rowIndex].aggregationFields?.splice(fieldIndex, 1);
    updateConfig({ contentRows: newRows });
  };

  const updateContentRowAggField = (rowIndex: number, fieldIndex: number, updates: Partial<AggregationDisplayConfig>) => {
    const newRows = [...(localConfig.contentRows || [])];
    if (newRows[rowIndex].aggregationFields) {
      newRows[rowIndex].aggregationFields![fieldIndex] = {
        ...newRows[rowIndex].aggregationFields![fieldIndex],
        ...updates,
      };
    }
    updateConfig({ contentRows: newRows });
  };

  // 🆕 집계 필드 순서 변경
  const moveContentRowAggField = (rowIndex: number, fieldIndex: number, direction: "up" | "down") => {
    const newRows = [...(localConfig.contentRows || [])];
    const fields = newRows[rowIndex].aggregationFields;
    if (!fields) return;

    const newIndex = direction === "up" ? fieldIndex - 1 : fieldIndex + 1;
    if (newIndex < 0 || newIndex >= fields.length) return;

    // 배열 요소 교환
    [fields[fieldIndex], fields[newIndex]] = [fields[newIndex], fields[fieldIndex]];
    updateConfig({ contentRows: newRows });
  };

  // contentRow 내 테이블 컬럼 관리 (table 타입)
  const addContentRowTableColumn = (rowIndex: number) => {
    const newRows = [...(localConfig.contentRows || [])];
    const newCol: TableColumnConfig = {
      id: `tcol-${Date.now()}`,
      field: "",
      label: "",
      type: "text",
      editable: false,
    };
    newRows[rowIndex].tableColumns = [...(newRows[rowIndex].tableColumns || []), newCol];
    updateConfig({ contentRows: newRows });
  };

  const removeContentRowTableColumn = (rowIndex: number, colIndex: number) => {
    const newRows = [...(localConfig.contentRows || [])];
    newRows[rowIndex].tableColumns?.splice(colIndex, 1);
    updateConfig({ contentRows: newRows });
  };

  const updateContentRowTableColumn = (rowIndex: number, colIndex: number, updates: Partial<TableColumnConfig>) => {
    const newRows = [...(localConfig.contentRows || [])];
    if (newRows[rowIndex].tableColumns) {
      newRows[rowIndex].tableColumns![colIndex] = { ...newRows[rowIndex].tableColumns![colIndex], ...updates };
    }
    updateConfig({ contentRows: newRows });
  };

  // 테이블 컬럼 순서 변경
  const moveContentRowTableColumn = (rowIndex: number, colIndex: number, direction: "up" | "down") => {
    const newRows = [...(localConfig.contentRows || [])];
    const columns = newRows[rowIndex].tableColumns;
    if (!columns) return;

    const newIndex = direction === "up" ? colIndex - 1 : colIndex + 1;
    if (newIndex < 0 || newIndex >= columns.length) return;

    // 컬럼 위치 교환
    const newColumns = [...columns];
    [newColumns[colIndex], newColumns[newIndex]] = [newColumns[newIndex], newColumns[colIndex]];
    newRows[rowIndex].tableColumns = newColumns;

    updateConfig({ contentRows: newRows });
  };

  // 행(Row) 순서 변경
  const moveContentRow = (rowIndex: number, direction: "up" | "down") => {
    const rows = localConfig.contentRows || [];
    if (rows.length <= 1) return;

    const newIndex = direction === "up" ? rowIndex - 1 : rowIndex + 1;
    if (newIndex < 0 || newIndex >= rows.length) return;

    // 행 위치 교환
    const newRows = [...rows];
    [newRows[rowIndex], newRows[newIndex]] = [newRows[newIndex], newRows[rowIndex]];

    updateConfig({ contentRows: newRows });
  };

  // === (레거시) Simple 모드 행/컬럼 관련 함수 ===
  const addRow = () => {
    const newRow: CardRowConfig = {
      id: `row-${Date.now()}`,
      columns: [],
      gap: "16px",
      layout: "horizontal",
    };
    updateConfig({
      cardLayout: [...(localConfig.cardLayout || []), newRow],
    });
  };

  const removeRow = (rowIndex: number) => {
    const newLayout = [...(localConfig.cardLayout || [])];
    newLayout.splice(rowIndex, 1);
    updateConfig({ cardLayout: newLayout });
  };

  const updateRow = (rowIndex: number, updates: Partial<CardRowConfig>) => {
    const newLayout = [...(localConfig.cardLayout || [])];
    newLayout[rowIndex] = { ...newLayout[rowIndex], ...updates };
    updateConfig({ cardLayout: newLayout });
  };

  const addColumn = (rowIndex: number) => {
    const newLayout = [...(localConfig.cardLayout || [])];
    const newColumn: CardColumnConfig = {
      id: `col-${Date.now()}`,
      field: "",
      label: "",
      type: "text",
      width: "auto",
      editable: true,
      required: false,
    };
    newLayout[rowIndex].columns.push(newColumn);
    updateConfig({ cardLayout: newLayout });
  };

  const removeColumn = (rowIndex: number, colIndex: number) => {
    const newLayout = [...(localConfig.cardLayout || [])];
    newLayout[rowIndex].columns.splice(colIndex, 1);
    updateConfig({ cardLayout: newLayout });
  };

  const updateColumn = (rowIndex: number, colIndex: number, updates: Partial<CardColumnConfig>) => {
    const newLayout = [...(localConfig.cardLayout || [])];
    newLayout[rowIndex].columns[colIndex] = {
      ...newLayout[rowIndex].columns[colIndex],
      ...updates,
    };
    updateConfig({ cardLayout: newLayout });
  };

  return (
    <div className="h-[calc(100vh-200px)] overflow-y-auto overflow-x-hidden">
      <div className="space-y-4 p-2 w-full">
        <Tabs value={activeTab} onValueChange={handleTabChange} className="w-full">
          <TabsList className="grid w-full grid-cols-5 h-auto p-1">
            <TabsTrigger value="basic" className="text-[9px] px-1 py-1">
              기본
            </TabsTrigger>
            <TabsTrigger value="data" className="text-[9px] px-1 py-1">
              소스
            </TabsTrigger>
            <TabsTrigger value="grouping" className="text-[9px] px-1 py-1">
              그룹
            </TabsTrigger>
            <TabsTrigger value="layout" className="text-[9px] px-1 py-1">
              레이아웃
            </TabsTrigger>
          </TabsList>

          {/* === 기본 설정 탭 === */}
          <TabsContent value="basic" className="space-y-3 mt-3">
            <div className="space-y-3 border rounded-lg p-3 bg-card">
              <h3 className="text-xs font-semibold">카드 설정</h3>

              {/* 카드 제목 표시 여부 */}
              <div className="flex items-center justify-between">
                <Label className="text-[10px]">카드 제목 표시</Label>
                <Switch
                  checked={localConfig.showCardTitle}
                  onCheckedChange={(checked) => updateConfig({ showCardTitle: checked })}
                  className="scale-75"
                />
              </div>

              {/* 카드 제목 설정 (표시할 때만) */}
              {localConfig.showCardTitle && (
                <div className="space-y-1.5">
                  <Label className="text-[10px]">카드 제목 템플릿</Label>
                  <CardTitleEditor
                    sourceTable={localConfig.dataSource?.sourceTable || ""}
                    currentValue={localConfig.cardTitle || ""}
                    onChange={(value) => {
                      setLocalConfig((prev) => ({ ...prev, cardTitle: value }));
                      updateConfig({ cardTitle: value });
                    }}
                  />
                </div>
              )}

              <div className="space-y-1.5">
                <Label className="text-[10px]">카드 간격</Label>
                <Select value={localConfig.cardSpacing} onValueChange={(value) => updateConfig({ cardSpacing: value })}>
                  <SelectTrigger className="h-7 text-[10px] w-full">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="8px">8px</SelectItem>
                    <SelectItem value="16px">16px</SelectItem>
                    <SelectItem value="24px">24px</SelectItem>
                    <SelectItem value="32px">32px</SelectItem>
                  </SelectContent>
                </Select>
              </div>

              <div className="flex items-center justify-between">
                <Label className="text-[10px]">테두리</Label>
                <Switch
                  checked={localConfig.showCardBorder}
                  onCheckedChange={(checked) => updateConfig({ showCardBorder: checked })}
                  className="scale-75"
                />
              </div>

              <div className="space-y-1.5">
                <Label className="text-[10px]">저장 모드</Label>
                <Select
                  value={localConfig.saveMode}
                  onValueChange={(value) => updateConfig({ saveMode: value as "all" | "individual" })}
                >
                  <SelectTrigger className="h-7 text-[10px] w-full">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="all">전체 저장</SelectItem>
                    <SelectItem value="individual">개별 저장</SelectItem>
                  </SelectContent>
                </Select>
              </div>
            </div>
          </TabsContent>

          {/* === 데이터 소스 탭 === */}
          <TabsContent value="data" className="space-y-3 mt-3">
            <div className="space-y-3 border rounded-lg p-3 bg-card">
              <h3 className="text-xs font-semibold">데이터 소스</h3>

              <div className="space-y-1.5">
                <Label className="text-[10px]">소스 테이블</Label>
                <TableSelector
                  value={localConfig.dataSource?.sourceTable || ""}
                  onChange={(value) =>
                    updateConfig({
                      dataSource: {
                        ...localConfig.dataSource,
                        sourceTable: value,
                      },
                    })
                  }
                />
              </div>

              <div className="space-y-1.5">
                <Label className="text-[10px]">필터 필드</Label>
                <Input
                  value={localConfig.dataSource?.filterField || ""}
                  onChange={(e) => {
                    setLocalConfig((prev) => ({
                      ...prev,
                      dataSource: {
                        ...prev.dataSource,
                        sourceTable: prev.dataSource?.sourceTable || "",
                        filterField: e.target.value,
                      },
                    }));
                    updateConfigDebounced({
                      dataSource: {
                        ...localConfig.dataSource,
                        sourceTable: localConfig.dataSource?.sourceTable || "",
                        filterField: e.target.value,
                      },
                    });
                  }}
                  placeholder="selectedIds"
                  className="h-7 text-[10px]"
                />
                <p className="text-[9px] text-muted-foreground">formData에서 가져올 필드</p>
              </div>
            </div>
          </TabsContent>

          {/* === 그룹핑 설정 탭 === */}
          <TabsContent value="grouping" className="space-y-3 mt-3 overflow-hidden">
            <div className="space-y-3 border rounded-lg p-3 bg-card overflow-hidden">
              <div className="flex items-center justify-between">
                <h3 className="text-xs font-semibold">그룹핑</h3>
                <Switch
                  checked={localConfig.grouping?.enabled}
                  onCheckedChange={(checked) => updateGrouping({ enabled: checked })}
                  className="scale-75"
                />
              </div>

              {localConfig.grouping?.enabled && (
                <>
                  <div className="space-y-1.5">
                    <Label className="text-[10px]">그룹 기준 필드</Label>
                    <SourceColumnSelector
                      sourceTable={localConfig.dataSource?.sourceTable || ""}
                      value={localConfig.grouping?.groupByField || ""}
                      onChange={(value) => updateGrouping({ groupByField: value })}
                      placeholder="예: part_code"
                    />
                    <p className="text-[9px] text-muted-foreground">같은 값을 가진 행들을 하나의 카드로 묶음</p>
                  </div>

                  {/* 집계 설정 */}
                  <div className="space-y-2 pt-2 border-t overflow-hidden">
                    <div className="flex items-center justify-between">
                      <Label className="text-[10px] font-semibold">집계 설정</Label>
                        <Button 
                          size="sm" 
                          variant="outline" 
                        onClick={() => setAggregationModalOpen(true)} 
                        className="h-6 text-[9px] px-2"
                        >
                        <Layers className="h-3 w-3 mr-1" />
                        설정 열기 ({(localConfig.grouping?.aggregations || []).length}개)
                        </Button>
                    </div>

                    {/* 현재 집계 목록 요약 */}
                    {(localConfig.grouping?.aggregations || []).length > 0 ? (
                      <div className="space-y-1 max-h-[120px] overflow-y-auto pr-1">
                    {(localConfig.grouping?.aggregations || []).map((agg, index) => (
                          <div 
                            key={`agg-summary-${index}`}
                            className={cn(
                              "flex items-center justify-between px-2 py-1 rounded text-[9px]",
                              agg.hidden ? "opacity-50" : "",
                              agg.sourceType === "formula" 
                                ? "bg-purple-50 border border-purple-200" 
                                : "bg-blue-50 border border-blue-200"
                            )}
                          >
                            <span className="truncate flex-1">
                              {agg.hidden && <span className="text-amber-600 mr-1">[숨김]</span>}
                              {agg.label || agg.resultField}
                            </span>
                            <Badge variant="outline" className="text-[8px] px-1 py-0 ml-1 shrink-0">
                              {agg.sourceType === "formula" ? "가상" : agg.type?.toUpperCase() || "SUM"}
                            </Badge>
                          </div>
                        ))}
                      </div>
                    ) : (
                      <p className="text-[9px] text-muted-foreground text-center py-2">
                        집계 설정이 없습니다
                      </p>
                    )}
                  </div>
                </>
              )}
            </div>
          </TabsContent>

          {/* === 레이아웃 설정 탭 === */}
          <TabsContent value="layout" className="space-y-3 mt-3">
            <div className="space-y-3 border rounded-lg p-3 bg-card">
              <div className="flex items-center justify-between">
                <h3 className="text-xs font-semibold">레이아웃 행</h3>
                  <Button
                    size="sm"
                    variant="outline"
                  onClick={() => setLayoutModalOpen(true)} 
                  className="h-6 text-[9px] px-2"
                  >
                    <Layers className="h-3 w-3 mr-1" />
                  설정 열기 ({(localConfig.contentRows || []).length}개)
                  </Button>
              </div>

              {/* 현재 레이아웃 요약 */}
              {(localConfig.contentRows || []).length > 0 ? (
                <div className="space-y-1 max-h-[200px] overflow-y-auto pr-1">
                  {(localConfig.contentRows || []).map((row, index) => {
                    const getRowTypeColor = (type: CardContentRowConfig["type"]) => {
                      switch (type) {
                        case "header": return "bg-blue-50 border-blue-200";
                        case "aggregation": return "bg-orange-50 border-orange-200";
                        case "table": return "bg-green-50 border-green-200";
                        case "fields": return "bg-purple-50 border-purple-200";
                        default: return "bg-gray-50 border-gray-200";
                      }
                    };
                    const getRowTypeLabel = (type: CardContentRowConfig["type"]) => {
                      switch (type) {
                        case "header": return "헤더";
                        case "aggregation": return "집계";
                        case "table": return "테이블";
                        case "fields": return "필드";
                        default: return type;
                      }
                    };
                    const getRowInfo = () => {
                      if (row.type === "header" || row.type === "fields") {
                        return `${(row.columns || []).length}개 컬럼`;
                      }
                      if (row.type === "aggregation") {
                        return `${(row.aggregationFields || []).length}개 필드`;
                      }
                      if (row.type === "table") {
                        return `${(row.tableColumns || []).length}개 컬럼${row.tableDataSource?.enabled ? " (외부)" : ""}`;
                      }
                      return "";
                    };

                    return (
                      <div 
                        key={`layout-summary-${index}`}
                        className={cn(
                          "flex items-center justify-between px-2 py-1.5 rounded text-[9px] border",
                          getRowTypeColor(row.type)
                        )}
                      >
                        <div className="flex items-center gap-2">
                          <Badge variant="outline" className="text-[8px] px-1 py-0">
                            {index + 1}
                          </Badge>
                          <span className="font-medium">{getRowTypeLabel(row.type)}</span>
                        </div>
                        <span className="text-muted-foreground">{getRowInfo()}</span>
                      </div>
                    );
                  })}
                </div>
              ) : (
                <div className="text-center py-4 border border-dashed rounded-lg">
                  <p className="text-[9px] text-muted-foreground">
                    레이아웃 행이 없습니다. 설정 열기를 클릭하여 추가하세요.
                  </p>
                </div>
              )}
            </div>
          </TabsContent>

        </Tabs>
      </div>

      {/* 집계 설정 모달 */}
      <AggregationSettingsModal
        open={aggregationModalOpen}
        onOpenChange={setAggregationModalOpen}
        aggregations={localConfig.grouping?.aggregations || []}
        sourceTable={localConfig.dataSource?.sourceTable || ""}
        allTables={allTables}
        contentRows={localConfig.contentRows || []}
        onSave={(newAggregations) => {
          updateGrouping({ aggregations: newAggregations });
        }}
      />

      {/* 레이아웃 설정 모달 */}
      <LayoutSettingsModal
        open={layoutModalOpen}
        onOpenChange={setLayoutModalOpen}
        contentRows={localConfig.contentRows || []}
        allTables={allTables}
        dataSourceTable={localConfig.dataSource?.sourceTable || ""}
        aggregations={localConfig.grouping?.aggregations || []}
        onSave={(newContentRows) => {
          updateConfig({ contentRows: newContentRows });
        }}
      />
    </div>
  );
}

// === 🆕 v3: 콘텐츠 행 설정 섹션 ===
function ContentRowConfigSection({
  row,
  rowIndex,
  totalRows,
  allTables,
  dataSourceTable,
  aggregations,
  onUpdateRow,
  onRemoveRow,
  onMoveRow,
  onAddColumn,
  onRemoveColumn,
  onUpdateColumn,
  onAddAggField,
  onRemoveAggField,
  onUpdateAggField,
  onMoveAggField,
  onAddTableColumn,
  onRemoveTableColumn,
  onUpdateTableColumn,
  onMoveTableColumn,
}: {
  row: CardContentRowConfig;
  rowIndex: number;
  totalRows: number;
  allTables: { tableName: string; displayName?: string }[];
  dataSourceTable: string;
  aggregations: AggregationConfig[];
  onUpdateRow: (updates: Partial<CardContentRowConfig>) => void;
  onRemoveRow: () => void;
  onMoveRow: (direction: "up" | "down") => void;
  onAddColumn: () => void;
  onRemoveColumn: (colIndex: number) => void;
  onUpdateColumn: (colIndex: number, updates: Partial<CardColumnConfig>) => void;
  onAddAggField: () => void;
  onRemoveAggField: (fieldIndex: number) => void;
  onUpdateAggField: (fieldIndex: number, updates: Partial<AggregationDisplayConfig>) => void;
  onMoveAggField: (fieldIndex: number, direction: "up" | "down") => void;
  onAddTableColumn: () => void;
  onRemoveTableColumn: (colIndex: number) => void;
  onUpdateTableColumn: (colIndex: number, updates: Partial<TableColumnConfig>) => void;
  onMoveTableColumn?: (colIndex: number, direction: "up" | "down") => void;
}) {
  // 로컬 상태로 Input 필드 관리 (타이핑 시 리렌더링 방지)
  const [localTableTitle, setLocalTableTitle] = useState(row.tableTitle || "");

  useEffect(() => {
    setLocalTableTitle(row.tableTitle || "");
  }, [row.tableTitle]);

  const handleTableTitleBlur = () => {
    if (localTableTitle !== row.tableTitle) {
      onUpdateRow({ tableTitle: localTableTitle });
    }
  };

  // 행 타입별 색상
  const typeColors = {
    header: "bg-purple-50 dark:bg-purple-950 border-purple-200 dark:border-purple-800",
    aggregation: "bg-orange-50 dark:bg-orange-950 border-orange-200 dark:border-orange-800",
    table: "bg-blue-50 dark:bg-blue-950 border-blue-200 dark:border-blue-800",
    fields: "bg-green-50 dark:bg-green-950 border-green-200 dark:border-green-800",
  };

  const typeLabels = {
    header: "헤더",
    aggregation: "집계",
    table: "테이블",
    fields: "필드",
  };

  const typeBadgeColors = {
    header: "bg-purple-100 text-purple-700",
    aggregation: "bg-orange-100 text-orange-700",
    table: "bg-blue-100 text-blue-700",
    fields: "bg-green-100 text-green-700",
  };

  return (
    <div className={cn("border rounded-lg p-2 space-y-2", typeColors[row.type])}>
      {/* 행 헤더 */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-1">
          {/* 순서 변경 버튼 */}
          <div className="flex flex-col">
            <Button
              size="sm"
              variant="ghost"
              onClick={() => onMoveRow("up")}
              disabled={rowIndex === 0}
              className="h-3 w-5 p-0"
              title="위로 이동"
            >
              <ChevronUp className="h-3 w-3" />
            </Button>
            <Button
              size="sm"
              variant="ghost"
              onClick={() => onMoveRow("down")}
              disabled={rowIndex === totalRows - 1}
              className="h-3 w-5 p-0"
              title="아래로 이동"
            >
              <ChevronDown className="h-3 w-3" />
            </Button>
          </div>
          <Badge className={cn("text-[9px] px-1 py-0", typeBadgeColors[row.type])}>
            행 {rowIndex + 1}: {typeLabels[row.type]}
          </Badge>
        </div>
        <Button size="sm" variant="ghost" onClick={onRemoveRow} className="h-5 w-5 p-0">
          <X className="h-3 w-3" />
        </Button>
      </div>

      {/* 타입 변경 */}
      <div className="space-y-1">
        <Label className="text-[9px]">타입 변경</Label>
        <Select
          value={row.type}
          onValueChange={(value) => onUpdateRow({ type: value as CardContentRowConfig["type"] })}
        >
          <SelectTrigger className="h-6 text-[10px] w-full">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="header">헤더</SelectItem>
            <SelectItem value="aggregation">집계</SelectItem>
            <SelectItem value="table">테이블</SelectItem>
            <SelectItem value="fields">필드</SelectItem>
          </SelectContent>
        </Select>
      </div>

      {/* 헤더/필드 타입 설정 */}
      {(row.type === "header" || row.type === "fields") && (
        <div className="space-y-2 pt-2 border-t">
          <div className="flex gap-2">
            <div className="flex-1 space-y-1 min-w-0">
              <Label className="text-[9px]">방향</Label>
              <Select
                value={row.layout || "horizontal"}
                onValueChange={(value) => onUpdateRow({ layout: value as "horizontal" | "vertical" })}
              >
                <SelectTrigger className="h-6 text-[10px] w-full">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="horizontal">가로</SelectItem>
                  <SelectItem value="vertical">세로</SelectItem>
                </SelectContent>
              </Select>
            </div>
            <div className="flex-1 space-y-1 min-w-0">
              <Label className="text-[9px]">배경색</Label>
              <Select
                value={row.backgroundColor || "none"}
                onValueChange={(value) => onUpdateRow({ backgroundColor: value === "none" ? undefined : value })}
              >
                <SelectTrigger className="h-6 text-[10px] w-full">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="none">없음</SelectItem>
                  <SelectItem value="blue">파랑</SelectItem>
                  <SelectItem value="green">초록</SelectItem>
                  <SelectItem value="purple">보라</SelectItem>
                  <SelectItem value="orange">주황</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>

          {/* 컬럼 목록 */}
          <div className="space-y-2 pl-2 border-l-2 border-primary/30">
            <div className="flex items-center justify-between">
              <Label className="text-[9px] font-semibold">컬럼 ({(row.columns || []).length}개)</Label>
              <Button size="sm" variant="outline" onClick={onAddColumn} className="h-5 text-[9px] px-1">
                <Plus className="h-2 w-2 mr-0.5" />
                추가
              </Button>
            </div>

            {(row.columns || []).map((col, colIndex) => (
              <ColumnConfigSection
                key={col.id || `col-${colIndex}`}
                col={col}
                colIndex={colIndex}
                allTables={allTables}
                dataSourceTable={dataSourceTable}
                aggregations={aggregations}
                onUpdate={(updates) => onUpdateColumn(colIndex, updates)}
                onRemove={() => onRemoveColumn(colIndex)}
              />
            ))}

            {(row.columns || []).length === 0 && (
              <div className="text-center py-2 text-[9px] text-muted-foreground border border-dashed rounded">
                컬럼 추가
              </div>
            )}
          </div>
        </div>
      )}

      {/* 집계 타입 설정 */}
      {row.type === "aggregation" && (
        <div className="space-y-2 pt-2 border-t">
          <div className="flex gap-2">
            <div className="flex-1 space-y-1 min-w-0">
              <Label className="text-[9px]">레이아웃</Label>
              <Select
                value={row.aggregationLayout || "horizontal"}
                onValueChange={(value) => onUpdateRow({ aggregationLayout: value as "horizontal" | "grid" })}
              >
                <SelectTrigger className="h-6 text-[10px] w-full">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="horizontal">가로 나열</SelectItem>
                  <SelectItem value="grid">그리드</SelectItem>
                </SelectContent>
              </Select>
            </div>
            {row.aggregationLayout === "grid" && (
              <div className="flex-1 space-y-1 min-w-0">
                <Label className="text-[9px]">컬럼 수</Label>
                <Select
                  value={String(row.aggregationColumns || 4)}
                  onValueChange={(value) => onUpdateRow({ aggregationColumns: Number(value) })}
                >
                  <SelectTrigger className="h-6 text-[10px] w-full">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="2">2개</SelectItem>
                    <SelectItem value="3">3개</SelectItem>
                    <SelectItem value="4">4개</SelectItem>
                  </SelectContent>
                </Select>
              </div>
            )}
          </div>

          {/* 집계 필드 목록 */}
          <div className="space-y-2 pl-2 border-l-2 border-orange-300">
            <div className="flex items-center justify-between">
              <Label className="text-[9px] font-semibold">집계 필드 ({(row.aggregationFields || []).length}개)</Label>
              <Button size="sm" variant="outline" onClick={onAddAggField} className="h-5 text-[9px] px-1">
                <Plus className="h-2 w-2 mr-0.5" />
                추가
              </Button>
            </div>

            {aggregations.length === 0 && (
              <p className="text-[9px] text-orange-600 bg-orange-100 dark:bg-orange-900 p-2 rounded">
                먼저 그룹 탭에서 집계 설정을 추가하세요
              </p>
            )}

            {(row.aggregationFields || []).map((field, fieldIndex) => (
              <div key={fieldIndex} className="border rounded p-2 space-y-1.5 bg-background">
                <div className="flex items-center justify-between">
                  <div className="flex items-center gap-1">
                    {/* 순서 변경 버튼 */}
                    <div className="flex flex-col">
                      <Button
                        size="sm"
                        variant="ghost"
                        onClick={() => onMoveAggField(fieldIndex, "up")}
                        disabled={fieldIndex === 0}
                        className="h-3 w-5 p-0"
                        title="위로 이동"
                      >
                        <ChevronUp className="h-3 w-3" />
                      </Button>
                      <Button
                        size="sm"
                        variant="ghost"
                        onClick={() => onMoveAggField(fieldIndex, "down")}
                        disabled={fieldIndex === (row.aggregationFields?.length || 0) - 1}
                        className="h-3 w-5 p-0"
                        title="아래로 이동"
                      >
                        <ChevronDown className="h-3 w-3" />
                      </Button>
                    </div>
                    <Badge variant="secondary" className="text-[9px] px-1 py-0">
                      집계 {fieldIndex + 1}
                    </Badge>
                  </div>
                  <Button size="sm" variant="ghost" onClick={() => onRemoveAggField(fieldIndex)} className="h-5 w-5 p-0">
                    <X className="h-3 w-3" />
                  </Button>
                </div>

                <div className="space-y-1">
                  <Label className="text-[9px]">집계 필드</Label>
                  <Select
                    value={field.aggregationResultField}
                    onValueChange={(value) => onUpdateAggField(fieldIndex, { aggregationResultField: value })}
                  >
                    <SelectTrigger className="h-6 text-[10px] w-full">
                      <SelectValue placeholder="선택" />
                    </SelectTrigger>
                    <SelectContent>
                      {aggregations.filter(agg => !agg.hidden).map((agg) => (
                        <SelectItem key={agg.resultField} value={agg.resultField}>
                          {agg.label || agg.resultField}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>

                <div className="space-y-1">
                  <Label className="text-[9px]">표시 라벨</Label>
                  <Input
                    value={field.label}
                    onChange={(e) => onUpdateAggField(fieldIndex, { label: e.target.value })}
                    placeholder="총수주잔량"
                    className="h-6 text-[10px]"
                  />
                </div>

                <div className="flex gap-2">
                  <div className="flex-1 space-y-1 min-w-0">
                    <Label className="text-[9px]">배경색</Label>
                    <Select
                      value={field.backgroundColor || "none"}
                      onValueChange={(value) => onUpdateAggField(fieldIndex, { backgroundColor: value === "none" ? undefined : value })}
                    >
                      <SelectTrigger className="h-6 text-[10px] w-full">
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="none">없음</SelectItem>
                        <SelectItem value="blue">파랑</SelectItem>
                        <SelectItem value="green">초록</SelectItem>
                        <SelectItem value="orange">주황</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>
                  <div className="flex-1 space-y-1 min-w-0">
                    <Label className="text-[9px]">폰트 크기</Label>
                    <Select
                      value={field.fontSize || "base"}
                      onValueChange={(value) => onUpdateAggField(fieldIndex, { fontSize: value as AggregationDisplayConfig["fontSize"] })}
                    >
                      <SelectTrigger className="h-6 text-[10px] w-full">
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="sm">작게</SelectItem>
                        <SelectItem value="base">보통</SelectItem>
                        <SelectItem value="lg">크게</SelectItem>
                        <SelectItem value="xl">매우 크게</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>
                </div>
              </div>
            ))}

            {(row.aggregationFields || []).length === 0 && aggregations.length > 0 && (
              <div className="text-center py-2 text-[9px] text-muted-foreground border border-dashed rounded">
                집계 필드 추가
              </div>
            )}
          </div>
        </div>
      )}

      {/* 테이블 타입 설정 */}
      {row.type === "table" && (
        <div className="space-y-2 pt-2 border-t">
          <div className="flex gap-2">
            <div className="flex-1 space-y-1 min-w-0">
              <Label className="text-[9px]">테이블 제목</Label>
              <Input
                value={localTableTitle}
                onChange={(e) => setLocalTableTitle(e.target.value)}
                onBlur={handleTableTitleBlur}
                onKeyDown={(e) => e.key === "Enter" && handleTableTitleBlur()}
                placeholder="선택사항"
                className="h-6 text-[10px]"
              />
            </div>
            <div className="flex items-center gap-1 pt-4">
              <Switch
                checked={row.showTableHeader !== false}
                onCheckedChange={(checked) => onUpdateRow({ showTableHeader: checked })}
                className="scale-[0.6]"
              />
              <Label className="text-[9px]">헤더</Label>
            </div>
          </div>

          {/* 외부 테이블 데이터 소스 설정 */}
          <div className="space-y-2 p-2 bg-blue-100/50 dark:bg-blue-900/20 rounded border border-blue-200 dark:border-blue-800">
            <div className="flex items-center gap-2">
              <Switch
                checked={row.tableDataSource?.enabled || false}
                onCheckedChange={(checked) =>
                  onUpdateRow({
                    tableDataSource: checked
                      ? { enabled: true, sourceTable: "", joinConditions: [] }
                      : undefined,
                  })
                }
                className="scale-[0.6]"
              />
              <Label className="text-[9px] font-semibold">외부 테이블 데이터 소스</Label>
            </div>

            {row.tableDataSource?.enabled && (
              <div className="space-y-2 pl-2">
                <div className="space-y-1">
                  <Label className="text-[9px]">소스 테이블</Label>
                  <Select
                    value={row.tableDataSource.sourceTable || ""}
                    onValueChange={(value) =>
                      onUpdateRow({
                        tableDataSource: { ...row.tableDataSource!, sourceTable: value },
                      })
                    }
                  >
                    <SelectTrigger className="h-6 text-[10px]">
                      <SelectValue placeholder="테이블 선택" />
                    </SelectTrigger>
                    <SelectContent>
                      {allTables.map((t) => (
                        <SelectItem key={t.tableName} value={t.tableName} className="text-[10px]">
                          {t.displayName || t.tableName}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>

                <div className="space-y-1.5">
                  <Label className="text-[9px]">조인 조건</Label>
                  <div className="space-y-1">
                    <div className="space-y-0.5">
                      <span className="text-[8px] text-muted-foreground">외부 테이블 키</span>
                      <SourceColumnSelector
                        sourceTable={row.tableDataSource.sourceTable}
                        value={row.tableDataSource.joinConditions?.[0]?.sourceKey || ""}
                        onChange={(value) =>
                          onUpdateRow({
                            tableDataSource: {
                              ...row.tableDataSource!,
                              joinConditions: [
                                {
                                  ...row.tableDataSource?.joinConditions?.[0],
                                  sourceKey: value,
                                  referenceKey: row.tableDataSource?.joinConditions?.[0]?.referenceKey || "",
                                },
                              ],
                            },
                          })
                        }
                        placeholder="키 선택"
                      />
                    </div>
                    <div className="space-y-0.5">
                      <span className="text-[8px] text-muted-foreground">카드 데이터 키</span>
                      <SourceColumnSelector
                        sourceTable={dataSourceTable}
                        value={row.tableDataSource.joinConditions?.[0]?.referenceKey || ""}
                        onChange={(value) =>
                          onUpdateRow({
                            tableDataSource: {
                              ...row.tableDataSource!,
                              joinConditions: [
                                {
                                  ...row.tableDataSource?.joinConditions?.[0],
                                  sourceKey: row.tableDataSource?.joinConditions?.[0]?.sourceKey || "",
                                  referenceKey: value,
                                },
                              ],
                            },
                          })
                        }
                        placeholder="키 선택"
                      />
                    </div>
                  </div>
                </div>

                <div className="space-y-1.5">
                  <div className="space-y-1">
                    <Label className="text-[9px]">정렬 컬럼</Label>
                    <SourceColumnSelector
                      sourceTable={row.tableDataSource.sourceTable}
                      value={row.tableDataSource.orderBy?.column || ""}
                      onChange={(value) =>
                        onUpdateRow({
                          tableDataSource: {
                            ...row.tableDataSource!,
                            orderBy: value ? { column: value, direction: row.tableDataSource?.orderBy?.direction || "desc" } : undefined,
                          },
                        })
                      }
                      placeholder="선택"
                    />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-[9px]">정렬 방향</Label>
                    <Select
                      value={row.tableDataSource.orderBy?.direction || "desc"}
                      onValueChange={(value) =>
                        onUpdateRow({
                          tableDataSource: {
                            ...row.tableDataSource!,
                            orderBy: row.tableDataSource?.orderBy?.column
                              ? { ...row.tableDataSource.orderBy, direction: value as "asc" | "desc" }
                              : undefined,
                          },
                        })
                      }
                    >
                      <SelectTrigger className="h-6 text-[10px]">
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="asc">오름차순</SelectItem>
                        <SelectItem value="desc">내림차순</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>
                </div>

                {/* 🆕 추가 조인 테이블 설정 */}
                <div className="space-y-2 pt-2 border-t">
                  <div className="flex items-center justify-between">
                    <Label className="text-[9px] font-semibold">조인 테이블 (선택)</Label>
                    <Button
                      size="sm"
                      variant="outline"
                      onClick={() => {
                        const newJoin = {
                          id: `join-${Date.now()}`,
                          joinTable: "",
                          joinType: "left" as const,
                          sourceKey: "",
                          targetKey: "",
                        };
                        onUpdateRow({
                          tableDataSource: {
                            ...row.tableDataSource!,
                            additionalJoins: [...(row.tableDataSource?.additionalJoins || []), newJoin],
                          },
                        });
                      }}
                      className="h-5 text-[9px] px-1"
                    >
                      <Plus className="h-2 w-2 mr-0.5" />
                      추가
                    </Button>
                  </div>
                  <p className="text-[8px] text-muted-foreground">
                    소스 테이블에 없는 컬럼을 다른 테이블에서 조인하여 가져옵니다
                  </p>

                  {(row.tableDataSource?.additionalJoins || []).map((join, joinIndex) => (
                    <div key={join.id} className="space-y-1.5 p-2 bg-purple-50 dark:bg-purple-900/20 rounded border border-purple-200 dark:border-purple-800">
                      <div className="flex items-center justify-between">
                        <Badge variant="secondary" className="text-[8px] px-1 py-0">
                          조인 {joinIndex + 1}
                        </Badge>
                        <Button
                          size="sm"
                          variant="ghost"
                          onClick={() => {
                            const newJoins = [...(row.tableDataSource?.additionalJoins || [])];
                            newJoins.splice(joinIndex, 1);
                            onUpdateRow({
                              tableDataSource: {
                                ...row.tableDataSource!,
                                additionalJoins: newJoins,
                              },
                            });
                          }}
                          className="h-4 w-4 p-0"
                        >
                          <X className="h-3 w-3" />
                        </Button>
                      </div>

                      {/* 조인 테이블 선택 */}
                      <div className="space-y-1">
                        <Label className="text-[9px]">조인 테이블</Label>
                        <TableSelector
                          allTables={allTables}
                          value={join.joinTable}
                          onChange={(value) => {
                            const newJoins = [...(row.tableDataSource?.additionalJoins || [])];
                            newJoins[joinIndex] = { ...join, joinTable: value };
                            onUpdateRow({
                              tableDataSource: {
                                ...row.tableDataSource!,
                                additionalJoins: newJoins,
                              },
                            });
                          }}
                          placeholder="테이블 선택"
                        />
                      </div>

                      {/* 조인 조건 */}
                      {join.joinTable && (
                        <div className="space-y-1">
                          <Label className="text-[9px]">조인 조건</Label>
                          <div className="flex gap-1 items-center">
                            <div className="flex-1">
                              <SourceColumnSelector
                                sourceTable={row.tableDataSource?.sourceTable || ""}
                                value={join.sourceKey}
                                onChange={(value) => {
                                  const newJoins = [...(row.tableDataSource?.additionalJoins || [])];
                                  newJoins[joinIndex] = { ...join, sourceKey: value };
                                  onUpdateRow({
                                    tableDataSource: {
                                      ...row.tableDataSource!,
                                      additionalJoins: newJoins,
                                    },
                                  });
                                }}
                                placeholder="소스 키"
                              />
                            </div>
                            <span className="text-[9px] text-muted-foreground">=</span>
                            <div className="flex-1">
                              <SourceColumnSelector
                                sourceTable={join.joinTable}
                                value={join.targetKey}
                                onChange={(value) => {
                                  const newJoins = [...(row.tableDataSource?.additionalJoins || [])];
                                  newJoins[joinIndex] = { ...join, targetKey: value };
                                  onUpdateRow({
                                    tableDataSource: {
                                      ...row.tableDataSource!,
                                      additionalJoins: newJoins,
                                    },
                                  });
                                }}
                                placeholder="조인 키"
                              />
                            </div>
                          </div>
                          <p className="text-[8px] text-muted-foreground">
                            {row.tableDataSource?.sourceTable}.{join.sourceKey || "?"} = {join.joinTable}.{join.targetKey || "?"}
                          </p>
                        </div>
                      )}
                    </div>
                  ))}

                  {(row.tableDataSource?.additionalJoins || []).length === 0 && (
                    <div className="text-center py-2 text-[8px] text-muted-foreground border border-dashed rounded">
                      조인 테이블 없음 (소스 테이블 컬럼만 사용)
                    </div>
                  )}
                </div>

                {/* 🆕 v3.4: 필터 설정 */}
                <div className="space-y-2 pt-2 border-t">
                  <div className="flex items-center justify-between">
                    <Label className="text-[9px] font-semibold">데이터 필터 (선택)</Label>
                    <Switch
                      checked={row.tableDataSource?.filterConfig?.enabled || false}
                      onCheckedChange={(checked) =>
                        onUpdateRow({
                          tableDataSource: {
                            ...row.tableDataSource!,
                            filterConfig: checked
                              ? {
                                  enabled: true,
                                  filterField: "",
                                  filterType: "equals",
                                  referenceField: "",
                                  referenceSource: "representativeData",
                                }
                              : undefined,
                          },
                        })
                      }
                      className="scale-[0.6]"
                    />
                  </div>
                  <p className="text-[8px] text-muted-foreground">
                    그룹 내 데이터를 특정 조건으로 필터링합니다 (같은 값만 / 다른 값만)
                  </p>

                  {row.tableDataSource?.filterConfig?.enabled && (
                    <div className="space-y-2 p-2 bg-amber-50 dark:bg-amber-900/20 rounded border border-amber-200 dark:border-amber-800">
                      {/* 필터 타입 */}
                      <div className="space-y-1">
                        <Label className="text-[9px]">필터 타입</Label>
                        <Select
                          value={row.tableDataSource.filterConfig.filterType}
                          onValueChange={(value) =>
                            onUpdateRow({
                              tableDataSource: {
                                ...row.tableDataSource!,
                                filterConfig: {
                                  ...row.tableDataSource!.filterConfig!,
                                  filterType: value as "equals" | "notEquals",
                                },
                              },
                            })
                          }
                        >
                          <SelectTrigger className="h-6 text-[10px]">
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            <SelectItem value="equals">같은 값만 (equals)</SelectItem>
                            <SelectItem value="notEquals">다른 값만 (notEquals)</SelectItem>
                          </SelectContent>
                        </Select>
                      </div>

                      {/* 필터 필드 */}
                      <div className="space-y-1">
                        <Label className="text-[9px]">필터 필드 (소스 테이블)</Label>
                        <SourceColumnSelector
                          sourceTable={row.tableDataSource.sourceTable}
                          value={row.tableDataSource.filterConfig.filterField}
                          onChange={(value) =>
                            onUpdateRow({
                              tableDataSource: {
                                ...row.tableDataSource!,
                                filterConfig: {
                                  ...row.tableDataSource!.filterConfig!,
                                  filterField: value,
                                },
                              },
                            })
                          }
                          placeholder="필터링할 컬럼 선택"
                        />
                        <p className="text-[8px] text-muted-foreground">
                          이 컬럼 값을 기준으로 필터링합니다
                        </p>
                      </div>

                      {/* 비교 기준 소스 */}
                      <div className="space-y-1">
                        <Label className="text-[9px]">비교 값 소스</Label>
                        <Select
                          value={row.tableDataSource.filterConfig.referenceSource}
                          onValueChange={(value) =>
                            onUpdateRow({
                              tableDataSource: {
                                ...row.tableDataSource!,
                                filterConfig: {
                                  ...row.tableDataSource!.filterConfig!,
                                  referenceSource: value as "formData" | "representativeData",
                                },
                              },
                            })
                          }
                        >
                          <SelectTrigger className="h-6 text-[10px]">
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            <SelectItem value="representativeData">카드 대표 데이터</SelectItem>
                            <SelectItem value="formData">폼 데이터 (formData)</SelectItem>
                          </SelectContent>
                        </Select>
                      </div>

                      {/* 비교 기준 필드 */}
                      <div className="space-y-1">
                        <Label className="text-[9px]">비교 기준 필드</Label>
                        {row.tableDataSource.filterConfig.referenceSource === "representativeData" ? (
                          <SourceColumnSelector
                            sourceTable={dataSourceTable}
                            value={row.tableDataSource.filterConfig.referenceField}
                            onChange={(value) =>
                              onUpdateRow({
                                tableDataSource: {
                                  ...row.tableDataSource!,
                                  filterConfig: {
                                    ...row.tableDataSource!.filterConfig!,
                                    referenceField: value,
                                  },
                                },
                              })
                            }
                            placeholder="비교할 필드 선택"
                          />
                        ) : (
                          <Input
                            value={row.tableDataSource.filterConfig.referenceField}
                            onChange={(e) =>
                              onUpdateRow({
                                tableDataSource: {
                                  ...row.tableDataSource!,
                                  filterConfig: {
                                    ...row.tableDataSource!.filterConfig!,
                                    referenceField: e.target.value,
                                  },
                                },
                              })
                            }
                            placeholder="formData 필드명 (예: selectedOrderNo)"
                            className="h-6 text-[10px]"
                          />
                        )}
                        <p className="text-[8px] text-muted-foreground">
                          이 값과 비교하여 필터링합니다
                        </p>
                      </div>

                      {/* 필터 조건 미리보기 */}
                      {row.tableDataSource.filterConfig.filterField && row.tableDataSource.filterConfig.referenceField && (
                        <div className="p-1.5 bg-amber-100 dark:bg-amber-800/30 rounded text-[9px]">
                          <span className="font-medium">조건: </span>
                          {row.tableDataSource.sourceTable}.{row.tableDataSource.filterConfig.filterField}
                          {row.tableDataSource.filterConfig.filterType === "equals" ? " = " : " != "}
                          {row.tableDataSource.filterConfig.referenceSource === "representativeData" 
                            ? `카드.${row.tableDataSource.filterConfig.referenceField}`
                            : `formData.${row.tableDataSource.filterConfig.referenceField}`
                          }
                        </div>
                      )}
                    </div>
                  )}
                </div>
              </div>
            )}
          </div>

          {/* CRUD 설정 */}
          <div className="space-y-2 p-2 bg-green-100/50 dark:bg-green-900/20 rounded border border-green-200 dark:border-green-800">
            <Label className="text-[9px] font-semibold">CRUD 설정</Label>
            <div className="flex flex-wrap gap-3">
              <div className="flex items-center gap-1">
                <Switch
                  checked={row.tableCrud?.allowCreate || false}
                  onCheckedChange={(checked) =>
                    onUpdateRow({
                      tableCrud: { ...row.tableCrud, allowCreate: checked, allowUpdate: row.tableCrud?.allowUpdate || false, allowDelete: row.tableCrud?.allowDelete || false },
                    })
                  }
                  className="scale-[0.5]"
                />
                <Label className="text-[9px]">추가</Label>
              </div>
              <div className="flex items-center gap-1">
                <Switch
                  checked={row.tableCrud?.allowUpdate || false}
                  onCheckedChange={(checked) =>
                    onUpdateRow({
                      tableCrud: { ...row.tableCrud, allowCreate: row.tableCrud?.allowCreate || false, allowUpdate: checked, allowDelete: row.tableCrud?.allowDelete || false },
                    })
                  }
                  className="scale-[0.5]"
                />
                <Label className="text-[9px]">수정</Label>
              </div>
              <div className="flex items-center gap-1">
                <Switch
                  checked={row.tableCrud?.allowDelete || false}
                  onCheckedChange={(checked) =>
                    onUpdateRow({
                      tableCrud: { ...row.tableCrud, allowCreate: row.tableCrud?.allowCreate || false, allowUpdate: row.tableCrud?.allowUpdate || false, allowDelete: checked },
                    })
                  }
                  className="scale-[0.5]"
                />
                <Label className="text-[9px]">삭제</Label>
              </div>
            </div>
            {row.tableCrud?.allowDelete && (
              <div className="flex items-center gap-1 pl-2">
                <Switch
                  checked={row.tableCrud?.deleteConfirm?.enabled !== false}
                  onCheckedChange={(checked) =>
                    onUpdateRow({
                      tableCrud: { ...row.tableCrud!, deleteConfirm: { enabled: checked } },
                    })
                  }
                  className="scale-[0.5]"
                />
                <Label className="text-[9px]">삭제 확인 팝업</Label>
              </div>
            )}
          </div>

          {/* 🆕 v3.12: 연동 저장 설정 */}
          <SyncSaveConfigSection
            row={row}
            allTables={allTables}
            onUpdateRow={onUpdateRow}
          />

          {/* 🆕 v3.13: 행 추가 시 자동 채번 설정 */}
          {row.tableCrud?.allowCreate && (
            <RowNumberingConfigSection
              row={row}
              onUpdateRow={onUpdateRow}
            />
          )}

          {/* 테이블 컬럼 목록 */}
          <div className="space-y-2 pl-2 border-l-2 border-blue-300">
            <div className="flex items-center justify-between">
              <Label className="text-[9px] font-semibold">테이블 컬럼 ({(row.tableColumns || []).length}개)</Label>
              <Button size="sm" variant="outline" onClick={onAddTableColumn} className="h-5 text-[9px] px-1">
                <Plus className="h-2 w-2 mr-0.5" />
                추가
              </Button>
            </div>

            {(row.tableColumns || []).map((col, colIndex) => (
              <TableColumnConfigSection
                key={col.id || `tcol-${colIndex}`}
                col={col}
                colIndex={colIndex}
                allTables={allTables}
                dataSourceTable={row.tableDataSource?.enabled ? row.tableDataSource.sourceTable : dataSourceTable}
                additionalJoins={row.tableDataSource?.additionalJoins || []}
                onUpdate={(updates) => onUpdateTableColumn(colIndex, updates)}
                onRemove={() => onRemoveTableColumn(colIndex)}
                onMoveUp={() => onMoveTableColumn?.(colIndex, "up")}
                onMoveDown={() => onMoveTableColumn?.(colIndex, "down")}
                isFirst={colIndex === 0}
                isLast={colIndex === (row.tableColumns || []).length - 1}
              />
            ))}

            {(row.tableColumns || []).length === 0 && (
              <div className="text-center py-2 text-[9px] text-muted-foreground border border-dashed rounded">
                테이블 컬럼 추가
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

// === (레거시) 행 설정 섹션 ===
function RowConfigSection({
  row,
  rowIndex,
  allTables,
  dataSourceTable,
  aggregations,
  onUpdateRow,
  onRemoveRow,
  onAddColumn,
  onRemoveColumn,
  onUpdateColumn,
  isHeader = false,
}: {
  row: CardRowConfig;
  rowIndex: number;
  allTables: { tableName: string; displayName?: string }[];
  dataSourceTable: string;
  aggregations: AggregationConfig[];
  onUpdateRow: (updates: Partial<CardRowConfig>) => void;
  onRemoveRow: () => void;
  onAddColumn: () => void;
  onRemoveColumn: (colIndex: number) => void;
  onUpdateColumn: (colIndex: number, updates: Partial<CardColumnConfig>) => void;
  isHeader?: boolean;
}) {
  return (
    <div className="border rounded-lg p-2 space-y-2 bg-background">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-1">
          <GripVertical className="h-3 w-3 text-muted-foreground" />
          <Badge variant="outline" className="text-[9px] px-1 py-0">
            행 {rowIndex + 1}
          </Badge>
          <span className="text-[9px] text-muted-foreground">({row.columns.length}개)</span>
        </div>
        <Button size="sm" variant="ghost" onClick={onRemoveRow} className="h-5 w-5 p-0">
          <X className="h-3 w-3" />
        </Button>
      </div>

      {/* 행 설정 */}
      <div className="flex gap-2">
        <div className="flex-1 space-y-1 min-w-0">
          <Label className="text-[9px]">방향</Label>
          <Select
            value={row.layout || "horizontal"}
            onValueChange={(value) => onUpdateRow({ layout: value as "horizontal" | "vertical" })}
          >
            <SelectTrigger className="h-6 text-[10px] w-full">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="horizontal">가로</SelectItem>
              <SelectItem value="vertical">세로</SelectItem>
            </SelectContent>
          </Select>
        </div>

        {isHeader && (
          <div className="flex-1 space-y-1 min-w-0">
            <Label className="text-[9px]">배경색</Label>
            <Select
              value={row.backgroundColor || "none"}
              onValueChange={(value) => onUpdateRow({ backgroundColor: value === "none" ? undefined : value })}
            >
              <SelectTrigger className="h-6 text-[10px] w-full">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="none">없음</SelectItem>
                <SelectItem value="blue">파랑</SelectItem>
                <SelectItem value="green">초록</SelectItem>
                <SelectItem value="purple">보라</SelectItem>
                <SelectItem value="orange">주황</SelectItem>
              </SelectContent>
            </Select>
          </div>
        )}
      </div>

      {/* 컬럼 목록 */}
      <div className="space-y-2 pl-2 border-l-2 border-primary/30">
        <div className="flex items-center justify-between">
          <Label className="text-[9px] font-semibold">컬럼</Label>
          <Button size="sm" variant="outline" onClick={onAddColumn} className="h-5 text-[9px] px-1">
            <Plus className="h-2 w-2 mr-0.5" />
            추가
          </Button>
        </div>

        {row.columns.map((col, colIndex) => (
          <ColumnConfigSection
            key={col.id || `col-${colIndex}`}
            col={col}
            colIndex={colIndex}
            allTables={allTables}
            dataSourceTable={dataSourceTable}
            aggregations={aggregations}
            onUpdate={(updates) => onUpdateColumn(colIndex, updates)}
            onRemove={() => onRemoveColumn(colIndex)}
          />
        ))}

        {row.columns.length === 0 && (
          <div className="text-center py-2 text-[9px] text-muted-foreground border border-dashed rounded">
            컬럼 추가
          </div>
        )}
      </div>
    </div>
  );
}

// === 컬럼 설정 섹션 (로컬 상태로 입력 필드 관리) ===
function ColumnConfigSection({
  col,
  colIndex,
  allTables,
  dataSourceTable,
  aggregations,
  onUpdate,
  onRemove,
}: {
  col: CardColumnConfig;
  colIndex: number;
  allTables: { tableName: string; displayName?: string }[];
  dataSourceTable: string;
  aggregations: AggregationConfig[];
  onUpdate: (updates: Partial<CardColumnConfig>) => void;
  onRemove: () => void;
}) {
  // 로컬 상태로 Input 필드 관리 (타이핑 시 리렌더링 방지)
  const [localField, setLocalField] = useState(col.field || "");
  const [localLabel, setLocalLabel] = useState(col.label || "");

  useEffect(() => {
    setLocalField(col.field || "");
    setLocalLabel(col.label || "");
  }, [col.field, col.label]);

  const handleFieldBlur = () => {
    if (localField !== col.field) {
      onUpdate({ field: localField });
    }
  };

  const handleLabelBlur = () => {
    if (localLabel !== col.label) {
      onUpdate({ label: localLabel });
    }
  };

  return (
    <div className="border rounded p-2 space-y-2 bg-background">
      <div className="flex items-center justify-between">
        <Badge variant="secondary" className="text-[9px] px-1 py-0">
          컬럼 {colIndex + 1}
        </Badge>
        <Button size="sm" variant="ghost" onClick={onRemove} className="h-5 w-5 p-0">
          <X className="h-3 w-3" />
        </Button>
      </div>

      {/* 기본 설정 */}
      <div className="space-y-1.5">
        <div className="space-y-1">
          <Label className="text-[9px]">필드명</Label>
          <Input
            value={localField}
            onChange={(e) => setLocalField(e.target.value)}
            onBlur={handleFieldBlur}
            onKeyDown={(e) => e.key === "Enter" && handleFieldBlur()}
            placeholder="field_name"
            className="h-6 text-[10px]"
          />
        </div>

        <div className="space-y-1">
          <Label className="text-[9px]">라벨</Label>
          <Input
            value={localLabel}
            onChange={(e) => setLocalLabel(e.target.value)}
            onBlur={handleLabelBlur}
            onKeyDown={(e) => e.key === "Enter" && handleLabelBlur()}
            placeholder="표시명"
            className="h-6 text-[10px]"
          />
        </div>

        <div className="flex gap-2">
          <div className="flex-1 space-y-1 min-w-0">
            <Label className="text-[9px]">타입</Label>
            <Select value={col.type} onValueChange={(value) => onUpdate({ type: value as any })}>
              <SelectTrigger className="h-6 text-[10px] w-full">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="text">텍스트</SelectItem>
                <SelectItem value="number">숫자</SelectItem>
                <SelectItem value="date">날짜</SelectItem>
                <SelectItem value="select">선택</SelectItem>
                <SelectItem value="aggregation">집계값</SelectItem>
              </SelectContent>
            </Select>
          </div>

          <div className="flex-1 space-y-1 min-w-0">
            <Label className="text-[9px]">너비</Label>
            <Select value={col.width || "auto"} onValueChange={(value) => onUpdate({ width: value })}>
              <SelectTrigger className="h-6 text-[10px] w-full">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="auto">자동</SelectItem>
                <SelectItem value="50%">50%</SelectItem>
                <SelectItem value="100%">100%</SelectItem>
              </SelectContent>
            </Select>
          </div>
        </div>

        {/* 집계값 타입일 때 */}
        {col.type === "aggregation" && aggregations.length > 0 && (
          <div className="space-y-1">
            <Label className="text-[9px]">집계 필드</Label>
            <Select
              value={col.aggregationField || ""}
              onValueChange={(value) => onUpdate({ aggregationField: value })}
            >
              <SelectTrigger className="h-6 text-[10px] w-full">
                <SelectValue placeholder="선택" />
              </SelectTrigger>
              <SelectContent>
                {aggregations.map((agg) => (
                  <SelectItem key={agg.resultField} value={agg.resultField}>
                    {agg.label || agg.resultField}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        )}
      </div>

      {/* 편집/필수 설정 */}
      <div className="flex items-center justify-between pt-1 border-t">
        <div className="flex items-center gap-1">
          <Switch
            checked={col.editable}
            onCheckedChange={(checked) => onUpdate({ editable: checked })}
            className="scale-[0.6]"
          />
          <Label className="text-[9px]">편집</Label>
        </div>
        <div className="flex items-center gap-1">
          <Switch
            checked={col.required}
            onCheckedChange={(checked) => onUpdate({ required: checked })}
            className="scale-[0.6]"
          />
          <Label className="text-[9px]">필수</Label>
        </div>
      </div>

      {/* 데이터 소스 설정 */}
      {col.type !== "aggregation" && (
        <div className="space-y-1.5 p-1.5 bg-blue-50 dark:bg-blue-950 rounded border border-blue-200 dark:border-blue-800">
          <Label className="text-[9px] font-semibold text-blue-600">소스</Label>
          <Select
            value={col.sourceConfig?.type || "manual"}
            onValueChange={(value) =>
              onUpdate({
                sourceConfig: {
                  ...col.sourceConfig,
                  type: value as "direct" | "join" | "manual",
                },
              })
            }
          >
            <SelectTrigger className="h-6 text-[10px] w-full">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="direct">직접</SelectItem>
              <SelectItem value="join">조인</SelectItem>
              <SelectItem value="manual">수동</SelectItem>
            </SelectContent>
          </Select>

          {col.sourceConfig?.type === "direct" && (
            <SourceColumnSelector
              sourceTable={dataSourceTable}
              value={col.sourceConfig.sourceColumn || ""}
              onChange={(value) =>
                onUpdate({
                  sourceConfig: {
                    ...col.sourceConfig,
                    type: "direct",
                    sourceColumn: value,
                  } as ColumnSourceConfig,
                })
              }
            />
          )}

          {col.sourceConfig?.type === "join" && (
            <div className="space-y-1">
              <Select
                value={col.sourceConfig.joinTable || ""}
                onValueChange={(value) =>
                  onUpdate({
                    sourceConfig: {
                      ...col.sourceConfig,
                      type: "join",
                      joinTable: value,
                    },
                  })
                }
              >
                <SelectTrigger className="h-6 text-[10px] w-full">
                  <SelectValue placeholder="조인 테이블" />
                </SelectTrigger>
                <SelectContent>
                  {(allTables || []).map((table) => (
                    <SelectItem key={table.tableName} value={table.tableName}>
                      {table.tableName}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>

              <SourceColumnSelector
                sourceTable={dataSourceTable}
                value={col.sourceConfig.joinKey || ""}
                onChange={(value) =>
                  onUpdate({
                    sourceConfig: {
                      ...col.sourceConfig,
                      type: "join",
                      joinKey: value,
                    } as ColumnSourceConfig,
                  })
                }
              />
            </div>
          )}
        </div>
      )}

      {/* 데이터 타겟 설정 */}
      <div className="space-y-1.5 p-1.5 bg-green-50 dark:bg-green-950 rounded border border-green-200 dark:border-green-800">
        <Label className="text-[9px] font-semibold text-green-600">저장</Label>

        <Select
          value={col.targetConfig?.targetTable || ""}
          onValueChange={(value) =>
            onUpdate({
              targetConfig: {
                ...col.targetConfig,
                targetTable: value,
                targetColumn: col.targetConfig?.targetColumn || "",
                saveEnabled: true,
              },
            })
          }
        >
          <SelectTrigger className="h-6 text-[10px] w-full">
            <SelectValue placeholder="테이블" />
          </SelectTrigger>
          <SelectContent>
            {(allTables || []).map((table) => (
              <SelectItem key={table.tableName} value={table.tableName}>
                {table.tableName}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>

        {col.targetConfig?.targetTable && (
          <SourceColumnSelector
            sourceTable={col.targetConfig.targetTable}
            value={col.targetConfig.targetColumn || ""}
            onChange={(value) =>
              onUpdate({
                targetConfig: {
                  ...col.targetConfig,
                  targetColumn: value,
                } as ColumnTargetConfig,
              })
            }
          />
        )}
      </div>
    </div>
  );
}

// === 테이블 컬럼 설정 섹션 (로컬 상태로 입력 필드 관리) ===
function TableColumnConfigSection({
  col,
  colIndex,
  allTables,
  dataSourceTable,
  additionalJoins,
  onUpdate,
  onRemove,
  onMoveUp,
  onMoveDown,
  isFirst,
  isLast,
}: {
  col: TableColumnConfig;
  colIndex: number;
  allTables: { tableName: string; displayName?: string }[];
  dataSourceTable: string;
  additionalJoins: { id: string; joinTable: string; joinType: string; sourceKey: string; targetKey: string }[];
  onUpdate: (updates: Partial<TableColumnConfig>) => void;
  onRemove: () => void;
  onMoveUp?: () => void;
  onMoveDown?: () => void;
  isFirst?: boolean;
  isLast?: boolean;
}) {
  // 로컬 상태로 Input 필드 관리 (타이핑 시 리렌더링 방지)
  const [localLabel, setLocalLabel] = useState(col.label || "");
  const [localWidth, setLocalWidth] = useState(col.width || "");

  // 선택된 테이블 (소스 테이블 또는 조인 테이블)
  const selectedTable = col.fromTable || dataSourceTable;
  const selectedJoinId = col.fromJoinId || "";

  // 사용 가능한 테이블 목록 (소스 테이블 + 조인 테이블들)
  const availableTables = [
    { id: "", table: dataSourceTable, label: `${dataSourceTable} (소스)` },
    ...additionalJoins
      .filter(j => j.joinTable)
      .map(j => ({ id: j.id, table: j.joinTable, label: `${j.joinTable} (조인)` })),
  ];

  useEffect(() => {
    setLocalLabel(col.label || "");
    setLocalWidth(col.width || "");
  }, [col.label, col.width]);

  const handleLabelBlur = () => {
    if (localLabel !== col.label) {
      onUpdate({ label: localLabel });
    }
  };

  const handleWidthBlur = () => {
    if (localWidth !== col.width) {
      onUpdate({ width: localWidth });
    }
  };

  return (
    <div className="border rounded p-2 space-y-2 bg-background">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-1">
          {/* 순서 변경 버튼 */}
          <div className="flex flex-col gap-0.5 mr-1">
            <Button
              size="sm"
              variant="ghost"
              onClick={onMoveUp}
              disabled={isFirst}
              className="h-3 w-4 p-0"
              title="위로 이동"
            >
              <ChevronUp className="h-2.5 w-2.5" />
            </Button>
            <Button
              size="sm"
              variant="ghost"
              onClick={onMoveDown}
              disabled={isLast}
              className="h-3 w-4 p-0"
              title="아래로 이동"
            >
              <ChevronDown className="h-2.5 w-2.5" />
            </Button>
          </div>
          <Badge variant="secondary" className="text-[9px] px-1 py-0">
            컬럼 {colIndex + 1}
          </Badge>
          {col.fromJoinId && (
            <Badge variant="outline" className="text-[8px] px-1 py-0 bg-purple-50 text-purple-700 border-purple-200">
              조인
            </Badge>
          )}
        </div>
        <Button size="sm" variant="ghost" onClick={onRemove} className="h-5 w-5 p-0">
          <X className="h-3 w-3" />
        </Button>
      </div>

      <div className="space-y-1.5">
        {/* 테이블 선택 (조인 테이블이 있을 때만 표시) */}
        {additionalJoins.length > 0 && (
          <div className="space-y-1">
            <Label className="text-[9px]">테이블</Label>
            <Select
              value={selectedJoinId ? `join:${selectedJoinId}` : "source"}
              onValueChange={(value) => {
                if (value === "source") {
                  onUpdate({ fromTable: undefined, fromJoinId: undefined, field: "" });
                } else {
                  const joinId = value.replace("join:", "");
                  const join = additionalJoins.find(j => j.id === joinId);
                  onUpdate({ fromTable: join?.joinTable, fromJoinId: joinId, field: "" });
                }
              }}
            >
              <SelectTrigger className="h-6 text-[10px]">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="source">{dataSourceTable} (소스)</SelectItem>
                {additionalJoins.filter(j => j.joinTable).map(j => (
                  <SelectItem key={j.id} value={`join:${j.id}`}>
                    {j.joinTable} (조인)
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        )}

        <div className="space-y-1">
          <Label className="text-[9px]">필드명</Label>
          <SourceColumnSelector
            sourceTable={selectedTable}
            value={col.field}
            onChange={(value) => onUpdate({ field: value })}
            placeholder="필드 선택"
          />
        </div>

        <div className="space-y-1">
          <Label className="text-[9px]">헤더 라벨</Label>
          <Input
            value={localLabel}
            onChange={(e) => setLocalLabel(e.target.value)}
            onBlur={handleLabelBlur}
            onKeyDown={(e) => e.key === "Enter" && handleLabelBlur()}
            placeholder="표시명"
            className="h-6 text-[10px]"
          />
        </div>

        <div className="flex gap-2">
          <div className="flex-1 space-y-1 min-w-0">
            <Label className="text-[9px]">타입</Label>
            <Select value={col.type} onValueChange={(value) => onUpdate({ type: value as any })}>
              <SelectTrigger className="h-6 text-[10px] w-full">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="text">텍스트</SelectItem>
                <SelectItem value="number">숫자</SelectItem>
                <SelectItem value="date">날짜</SelectItem>
                <SelectItem value="badge">배지</SelectItem>
              </SelectContent>
            </Select>
          </div>

          <div className="flex-1 space-y-1 min-w-0">
            <Label className="text-[9px]">너비</Label>
            <Input
              value={localWidth}
              onChange={(e) => setLocalWidth(e.target.value)}
              onBlur={handleWidthBlur}
              onKeyDown={(e) => e.key === "Enter" && handleWidthBlur()}
              placeholder="100px"
              className="h-6 text-[10px]"
            />
          </div>
        </div>
      </div>

      {/* 편집 설정 */}
      <div className="flex items-center justify-between pt-1 border-t">
        <div className="flex items-center gap-1">
          <Switch
            checked={col.editable}
            onCheckedChange={(checked) => onUpdate({ editable: checked })}
            className="scale-[0.6]"
          />
          <Label className="text-[9px]">편집 가능</Label>
        </div>
      </div>

      {/* 편집 가능할 때 저장 설정 */}
      {col.editable && (
        <div className="space-y-1.5 p-1.5 bg-green-50 dark:bg-green-950 rounded border border-green-200 dark:border-green-800">
          <Label className="text-[9px] font-semibold text-green-600">저장</Label>

          <Select
            value={col.targetConfig?.targetTable || ""}
            onValueChange={(value) =>
              onUpdate({
                targetConfig: {
                  ...col.targetConfig,
                  targetTable: value,
                  targetColumn: col.targetConfig?.targetColumn || "",
                  saveEnabled: true,
                },
              })
            }
          >
            <SelectTrigger className="h-6 text-[10px] w-full">
              <SelectValue placeholder="테이블" />
            </SelectTrigger>
            <SelectContent>
              {(allTables || []).map((table) => (
                <SelectItem key={table.tableName} value={table.tableName}>
                  {table.tableName}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>

          {col.targetConfig?.targetTable && (
            <SourceColumnSelector
              sourceTable={col.targetConfig.targetTable}
              value={col.targetConfig.targetColumn || ""}
              onChange={(value) =>
                onUpdate({
                  targetConfig: {
                    ...col.targetConfig,
                    targetColumn: value,
                  } as ColumnTargetConfig,
                })
              }
            />
          )}
        </div>
      )}
    </div>
  );
}
