"use client";

/**
 * V2Repeater 설정 패널
 *
 * 렌더링 모드별 설정:
 * - inline: 현재 화면 테이블 컬럼 직접 입력
 * - modal: 엔티티 선택 + 추가 입력 (FK 저장 + 추가 컬럼 입력)
 */

import React, { useState, useEffect, useMemo, useCallback } from "react";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { Checkbox } from "@/components/ui/checkbox";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
import {
  Database,
  Link2,
  Plus,
  Trash2,
  GripVertical,
  ArrowRight,
  Calculator,
  ChevronDown,
  ChevronRight,
  Eye,
  EyeOff,
  Wand2,
  Check,
  ChevronsUpDown,
  Settings,
  Rows3,
  Columns3,
  MousePointerClick,
} from "lucide-react";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { tableTypeApi } from "@/lib/api/screen";
import { tableManagementApi } from "@/lib/api/tableManagement";
import { entityJoinApi } from "@/lib/api/entityJoin";
import { getAvailableNumberingRules, getAvailableNumberingRulesForScreen } from "@/lib/api/numberingRule";
import { NumberingRuleConfig } from "@/types/numbering-rule";
import { cn } from "@/lib/utils";
import { V2RepeaterConfig, RepeaterColumnConfig, DEFAULT_REPEATER_CONFIG } from "@/types/v2-repeater";

// 테이블 엔티티 관계 정보
interface TableRelation {
  tableName: string;
  tableLabel: string;
  foreignKeyColumn: string; // 저장 테이블의 FK 컬럼
  referenceColumn: string; // 마스터 테이블의 PK 컬럼
}

interface V2RepeaterConfigPanelProps {
  config: V2RepeaterConfig;
  onChange: (config: V2RepeaterConfig) => void;
  currentTableName?: string;
  screenTableName?: string;
  tableColumns?: any[];
  menuObjid?: number | string; // 🆕 메뉴 ID (채번 규칙 조회용)
}

interface ColumnOption {
  columnName: string;
  displayName: string;
  inputType?: string;
  detailSettings?: {
    codeGroup?: string;
    referenceTable?: string;
    referenceColumn?: string;
    displayColumn?: string;
    format?: string;
  };
}

interface EntityColumnOption {
  columnName: string;
  displayName: string;
  referenceTable?: string;
  referenceColumn?: string;
  displayColumn?: string;
}

interface CalculationRule {
  id: string;
  targetColumn: string;
  formula: string;
  label?: string;
}

export const V2RepeaterConfigPanel: React.FC<V2RepeaterConfigPanelProps> = ({
  config: propConfig,
  onChange,
  currentTableName: propCurrentTableName,
  screenTableName,
  menuObjid,
}) => {
  const currentTableName = screenTableName || propCurrentTableName;

  // config 안전하게 초기화
  const config: V2RepeaterConfig = useMemo(() => {
    const merged = {
      ...DEFAULT_REPEATER_CONFIG,
      ...propConfig,
      renderMode: propConfig?.renderMode || DEFAULT_REPEATER_CONFIG.renderMode,
      dataSource: {
        ...DEFAULT_REPEATER_CONFIG.dataSource,
        ...propConfig?.dataSource,
      },
      columns: propConfig?.columns || [],
      modal: {
        ...DEFAULT_REPEATER_CONFIG.modal,
        ...propConfig?.modal,
      } as V2RepeaterConfig["modal"],
      features: {
        ...DEFAULT_REPEATER_CONFIG.features,
        ...propConfig?.features,
      } as V2RepeaterConfig["features"],
    };
    return merged as V2RepeaterConfig;
  }, [propConfig]);

  // 상태 관리
  const [currentTableColumns, setCurrentTableColumns] = useState<ColumnOption[]>([]); // 현재 테이블 컬럼
  const [entityColumns, setEntityColumns] = useState<EntityColumnOption[]>([]); // 엔티티 타입 컬럼
  const [sourceTableColumns, setSourceTableColumns] = useState<ColumnOption[]>([]); // 소스(엔티티) 테이블 컬럼
  const [calculationRules, setCalculationRules] = useState<CalculationRule[]>(config.calculationRules || []);

  const [loadingColumns, setLoadingColumns] = useState(false);
  const [loadingSourceColumns, setLoadingSourceColumns] = useState(false);

  // 저장 테이블 관련 상태
  const [allTables, setAllTables] = useState<Array<{ tableName: string; displayName: string }>>([]);
  const [loadingTables, setLoadingTables] = useState(false);
  const [relatedTables, setRelatedTables] = useState<TableRelation[]>([]); // 현재 테이블과 연관된 테이블 목록
  const [loadingRelations, setLoadingRelations] = useState(false);
  const [tableComboboxOpen, setTableComboboxOpen] = useState(false); // 테이블 Combobox 열림 상태

  // Entity 조인 관련 상태
  const [entityJoinData, setEntityJoinData] = useState<{
    joinTables: Array<{
      tableName: string;
      currentDisplayColumn: string;
      joinConfig?: { sourceColumn?: string };
      availableColumns: Array<{
        columnName: string;
        columnLabel: string;
        dataType: string;
        inputType?: string;
      }>;
    }>;
    availableColumns: Array<{
      tableName: string;
      columnName: string;
      columnLabel: string;
      joinAlias: string;
    }>;
  }>({ joinTables: [], availableColumns: [] });
  const [loadingEntityJoins, setLoadingEntityJoins] = useState(false);

  // 🆕 확장된 컬럼 (상세 설정 표시용)
  const [expandedColumn, setExpandedColumn] = useState<string | null>(null);

  // Collapsible 상태
  const [featureOptionsOpen, setFeatureOptionsOpen] = useState(true);
  const [columnSelectOpen, setColumnSelectOpen] = useState(true);
  const [selectedColumnsOpen, setSelectedColumnsOpen] = useState(true);
  const [calcRulesOpen, setCalcRulesOpen] = useState(false);
  const [entityJoinSubOpen, setEntityJoinSubOpen] = useState<Record<number, boolean>>({});
  const [configuredJoinsOpen, setConfiguredJoinsOpen] = useState(false);

  // 🆕 채번 규칙 목록
  const [numberingRules, setNumberingRules] = useState<NumberingRuleConfig[]>([]);
  const [loadingNumberingRules, setLoadingNumberingRules] = useState(false);

  // 🆕 대상 메뉴 목록 (채번 규칙 선택용)
  const [parentMenus, setParentMenus] = useState<any[]>([]);
  const [loadingMenus, setLoadingMenus] = useState(false);

  // 🆕 선택된 메뉴 OBJID (컬럼별로 저장, 한 번 선택하면 공유)
  const [selectedMenuObjid, setSelectedMenuObjid] = useState<number | undefined>(() => {
    // 기존 config에서 저장된 값이 있으면 복원
    const existingAutoFill = config.columns.find(
      (c) => c.autoFill?.type === "numbering" && c.autoFill.selectedMenuObjid,
    );
    return existingAutoFill?.autoFill?.selectedMenuObjid || (menuObjid ? Number(menuObjid) : undefined);
  });

  // 자동 입력 타입 옵션
  const autoFillOptions = [
    { value: "none", label: "없음" },
    { value: "currentDate", label: "현재 날짜" },
    { value: "currentDateTime", label: "현재 날짜+시간" },
    { value: "sequence", label: "순번 (1, 2, 3...)" },
    { value: "numbering", label: "채번 규칙" },
    { value: "fromMainForm", label: "메인 폼에서 복사" },
    { value: "fixed", label: "고정값" },
    { value: "parentSequence", label: "부모채번+순번 (예: WO-001-01)" },
  ];

  // 🆕 대상 메뉴 목록 로드 (사용자 메뉴의 레벨 2)
  useEffect(() => {
    const loadMenus = async () => {
      setLoadingMenus(true);
      try {
        const { apiClient } = await import("@/lib/api/client");
        const response = await apiClient.get("/admin/menus");

        if (response.data.success && response.data.data) {
          const allMenus = response.data.data;

          // 사용자 메뉴(menu_type='1')의 레벨 2만 필터링
          const level2UserMenus = allMenus.filter((menu: any) => menu.menu_type === "1" && menu.lev === 2);

          setParentMenus(level2UserMenus);
        }
      } catch (error) {
        console.error("부모 메뉴 로드 실패:", error);
      } finally {
        setLoadingMenus(false);
      }
    };
    loadMenus();
  }, []);

  // 🆕 채번 규칙 로드 (선택된 메뉴 기준)
  useEffect(() => {
    const loadNumberingRules = async () => {
      // 메뉴가 선택되지 않았으면 로드하지 않음
      if (!selectedMenuObjid) {
        setNumberingRules([]);
        return;
      }

      setLoadingNumberingRules(true);
      try {
        const result = await getAvailableNumberingRules(selectedMenuObjid);

        if (result?.success && result.data) {
          setNumberingRules(result.data);
        }
      } catch (error) {
        console.error("채번 규칙 로드 실패:", error);
        setNumberingRules([]);
      } finally {
        setLoadingNumberingRules(false);
      }
    };
    loadNumberingRules();
  }, [selectedMenuObjid]);

  // 전체 테이블 목록 로드
  useEffect(() => {
    const loadTables = async () => {
      setLoadingTables(true);
      try {
        const response = await tableManagementApi.getTableList();
        if (response.success && response.data) {
          setAllTables(
            response.data.map((t: any) => ({
              tableName: t.tableName || t.table_name,
              displayName: t.displayName || t.table_label || t.tableName || t.table_name,
            })),
          );
        }
      } catch (error) {
        console.error("테이블 목록 로드 실패:", error);
      } finally {
        setLoadingTables(false);
      }
    };
    loadTables();
  }, []);

  // 연관 테이블 목록 로드 (엔티티 관계 기반)
  // 1. 화면 메인 테이블이 있으면: 그 테이블을 참조하는 테이블 (자식 테이블)
  // 2. 저장 테이블이 선택되었으면: 그 테이블을 참조하는 테이블도 추가
  useEffect(() => {
    const loadRelatedTables = async () => {
      // 화면 메인 테이블 또는 저장 테이블 중 하나라도 있어야 함
      const baseTable = currentTableName || config.mainTableName;
      if (!baseTable) {
        setRelatedTables([]);
        return;
      }

      setLoadingRelations(true);
      try {
        const { apiClient } = await import("@/lib/api/client");
        const allRelations: TableRelation[] = [];

        // 1. 화면 메인 테이블을 참조하는 테이블 조회 (자식 테이블)
        if (currentTableName) {
          const response = await apiClient.get(`/table-management/columns/${currentTableName}/referenced-by`);
          if (response.data.success && response.data.data) {
            const relations: TableRelation[] = response.data.data.map((rel: any) => ({
              tableName: rel.tableName || rel.table_name,
              tableLabel: rel.tableLabel || rel.table_label || rel.tableName || rel.table_name,
              foreignKeyColumn: rel.columnName || rel.column_name, // FK 컬럼 (자식 테이블의)
              referenceColumn: rel.referenceColumn || rel.reference_column || "id", // PK 컬럼 (부모 테이블의)
            }));
            allRelations.push(...relations);
          }
        }

        // 2. 저장 테이블이 화면 메인 테이블과 다르면, 저장 테이블을 참조하는 테이블도 조회
        if (config.mainTableName && config.mainTableName !== currentTableName) {
          const response2 = await apiClient.get(`/table-management/columns/${config.mainTableName}/referenced-by`);
          if (response2.data.success && response2.data.data) {
            const relations2: TableRelation[] = response2.data.data.map((rel: any) => ({
              tableName: rel.tableName || rel.table_name,
              tableLabel: rel.tableLabel || rel.table_label || rel.tableName || rel.table_name,
              foreignKeyColumn: rel.columnName || rel.column_name,
              referenceColumn: rel.referenceColumn || rel.reference_column || "id",
            }));
            // 중복 제거 후 추가
            relations2.forEach((rel) => {
              if (!allRelations.some((r) => r.tableName === rel.tableName)) {
                allRelations.push(rel);
              }
            });
          }
        }

        setRelatedTables(allRelations);
      } catch (error) {
        console.error("연관 테이블 로드 실패:", error);
        setRelatedTables([]);
      } finally {
        setLoadingRelations(false);
      }
    };
    loadRelatedTables();
  }, [currentTableName, config.mainTableName]);

  // Entity 조인 컬럼 정보 로드 (저장 테이블 기준)
  const entityJoinTargetTable = config.useCustomTable && config.mainTableName ? config.mainTableName : currentTableName;

  useEffect(() => {
    const fetchEntityJoinColumns = async () => {
      if (!entityJoinTargetTable) return;
      setLoadingEntityJoins(true);
      try {
        const result = await entityJoinApi.getEntityJoinColumns(entityJoinTargetTable);
        setEntityJoinData({
          joinTables: result.joinTables || [],
          availableColumns: result.availableColumns || [],
        });
      } catch (error) {
        console.error("Entity 조인 컬럼 조회 오류:", error);
        setEntityJoinData({ joinTables: [], availableColumns: [] });
      } finally {
        setLoadingEntityJoins(false);
      }
    };
    fetchEntityJoinColumns();
  }, [entityJoinTargetTable]);

  // 설정 업데이트 헬퍼
  const updateConfig = useCallback(
    (updates: Partial<V2RepeaterConfig>) => {
      onChange({ ...config, ...updates });
    },
    [config, onChange],
  );

  // Entity 조인 컬럼 토글 (추가/제거)
  const toggleEntityJoinColumn = useCallback(
    (
      joinTableName: string,
      sourceColumn: string,
      refColumnName: string,
      refColumnLabel: string,
      displayField: string,
      columnType?: string,
    ) => {
      const currentJoins = config.entityJoins || [];
      const existingJoinIdx = currentJoins.findIndex(
        (j) => j.sourceColumn === sourceColumn && j.referenceTable === joinTableName,
      );

      let newEntityJoins = [...currentJoins];
      let newColumns = [...config.columns];

      if (existingJoinIdx >= 0) {
        const existingJoin = currentJoins[existingJoinIdx];
        const existingColIdx = existingJoin.columns.findIndex((c) => c.referenceField === refColumnName);

        if (existingColIdx >= 0) {
          const updatedColumns = existingJoin.columns.filter((_, i) => i !== existingColIdx);
          if (updatedColumns.length === 0) {
            newEntityJoins = newEntityJoins.filter((_, i) => i !== existingJoinIdx);
          } else {
            newEntityJoins[existingJoinIdx] = { ...existingJoin, columns: updatedColumns };
          }
          // config.columns에서도 제거
          newColumns = newColumns.filter((c) => !(c.key === displayField && c.isJoinColumn));
        } else {
          newEntityJoins[existingJoinIdx] = {
            ...existingJoin,
            columns: [...existingJoin.columns, { referenceField: refColumnName, displayField }],
          };
          // config.columns에 추가
          newColumns.push({
            key: displayField,
            title: refColumnLabel,
            width: "auto",
            visible: true,
            editable: false,
            isJoinColumn: true,
            inputType: columnType || "text",
          });
        }
      } else {
        newEntityJoins.push({
          sourceColumn,
          referenceTable: joinTableName,
          columns: [{ referenceField: refColumnName, displayField }],
        });
        // config.columns에 추가
        newColumns.push({
          key: displayField,
          title: refColumnLabel,
          width: "auto",
          visible: true,
          editable: false,
          isJoinColumn: true,
          inputType: columnType || "text",
        });
      }

      updateConfig({ entityJoins: newEntityJoins, columns: newColumns });
    },
    [config.entityJoins, config.columns, updateConfig],
  );

  // Entity 조인에 특정 컬럼이 설정되어 있는지 확인
  const isEntityJoinColumnActive = useCallback(
    (joinTableName: string, sourceColumn: string, refColumnName: string) => {
      return (config.entityJoins || []).some(
        (j) =>
          j.sourceColumn === sourceColumn &&
          j.referenceTable === joinTableName &&
          j.columns.some((c) => c.referenceField === refColumnName),
      );
    },
    [config.entityJoins],
  );

  const updateDataSource = useCallback(
    (field: string, value: any) => {
      updateConfig({
        dataSource: { ...config.dataSource, [field]: value },
      });
    },
    [config.dataSource, updateConfig],
  );

  const updateModal = useCallback(
    (field: string, value: any) => {
      updateConfig({
        modal: { ...config.modal, [field]: value } as V2RepeaterConfig["modal"],
      });
    },
    [config.modal, updateConfig],
  );

  const updateFeatures = useCallback(
    (field: string, value: boolean) => {
      updateConfig({
        features: { ...config.features, [field]: value },
      });
    },
    [config.features, updateConfig],
  );

  // 저장 테이블 선택 핸들러 - 엔티티 관계에서 FK/PK 자동 설정
  const handleSaveTableSelect = useCallback(
    (tableName: string) => {
      // 빈 값 선택 시 (현재 테이블로 복원)
      if (!tableName || tableName === currentTableName) {
        updateConfig({
          useCustomTable: false,
          mainTableName: undefined,
          foreignKeyColumn: undefined,
          foreignKeySourceColumn: undefined,
        });
        return;
      }

      // 연관 테이블에서 FK 관계 찾기
      const relation = relatedTables.find((r) => r.tableName === tableName);

      if (relation) {
        // 엔티티 관계가 있으면 자동으로 FK/PK 설정
        updateConfig({
          useCustomTable: true,
          mainTableName: tableName,
          foreignKeyColumn: relation.foreignKeyColumn,
          foreignKeySourceColumn: relation.referenceColumn,
        });
      } else {
        // 엔티티 관계가 없으면 직접 입력 필요
        updateConfig({
          useCustomTable: true,
          mainTableName: tableName,
          foreignKeyColumn: undefined,
          foreignKeySourceColumn: "id",
        });
      }
    },
    [currentTableName, relatedTables, updateConfig],
  );

  // 저장 테이블 컬럼 로드 (저장 테이블이 설정되면 해당 테이블, 아니면 현재 화면 테이블)
  // 실제 저장할 테이블의 컬럼을 보여줘야 함
  const targetTableForColumns = config.useCustomTable && config.mainTableName ? config.mainTableName : currentTableName;

  useEffect(() => {
    const loadCurrentTableColumns = async () => {
      if (!targetTableForColumns) {
        setCurrentTableColumns([]);
        setEntityColumns([]);
        return;
      }

      setLoadingColumns(true);
      try {
        const columnData = await tableTypeApi.getColumns(targetTableForColumns);
        const cols: ColumnOption[] = [];
        const entityCols: EntityColumnOption[] = [];

        for (const c of columnData) {
          // detailSettings 파싱
          let detailSettings: any = null;
          if (c.detailSettings) {
            try {
              detailSettings = typeof c.detailSettings === "string" ? JSON.parse(c.detailSettings) : c.detailSettings;
            } catch (e) {
              console.warn("detailSettings 파싱 실패:", c.detailSettings);
            }
          }

          const col: ColumnOption = {
            columnName: c.columnName || c.column_name,
            displayName: c.displayName || c.columnLabel || c.columnName || c.column_name,
            inputType: c.inputType || c.input_type,
            detailSettings: detailSettings
              ? {
                  codeGroup: detailSettings.codeGroup,
                  referenceTable: detailSettings.referenceTable,
                  referenceColumn: detailSettings.referenceColumn,
                  displayColumn: detailSettings.displayColumn,
                  format: detailSettings.format,
                }
              : undefined,
          };
          cols.push(col);

          // 엔티티 타입 컬럼 감지
          if (col.inputType === "entity") {
            const referenceTable = detailSettings?.referenceTable || c.referenceTable;
            const referenceColumn = detailSettings?.referenceColumn || c.referenceColumn || "id";
            const displayColumn = detailSettings?.displayColumn || c.displayColumn;

            if (referenceTable) {
              entityCols.push({
                columnName: col.columnName,
                displayName: col.displayName,
                referenceTable,
                referenceColumn,
                displayColumn,
              });
            }
          }
        }

        setCurrentTableColumns(cols);
        setEntityColumns(entityCols);
      } catch (error) {
        console.error("저장 테이블 컬럼 로드 실패:", error);
        setCurrentTableColumns([]);
        setEntityColumns([]);
      } finally {
        setLoadingColumns(false);
      }
    };
    loadCurrentTableColumns();
  }, [targetTableForColumns]);

  // 소스(엔티티) 테이블 컬럼 로드 (모달 모드일 때)
  useEffect(() => {
    const loadSourceTableColumns = async () => {
      const sourceTable = config.dataSource?.sourceTable;
      if (!sourceTable) {
        setSourceTableColumns([]);
        return;
      }

      setLoadingSourceColumns(true);
      try {
        const columnData = await tableTypeApi.getColumns(sourceTable);
        const cols: ColumnOption[] = columnData.map((c: any) => ({
          columnName: c.columnName || c.column_name,
          displayName: c.displayName || c.columnLabel || c.columnName || c.column_name,
          inputType: c.inputType || c.input_type,
        }));
        setSourceTableColumns(cols);
      } catch (error) {
        console.error("소스 테이블 컬럼 로드 실패:", error);
        setSourceTableColumns([]);
      } finally {
        setLoadingSourceColumns(false);
      }
    };

    if (config.renderMode === "modal") {
      loadSourceTableColumns();
    }
  }, [config.dataSource?.sourceTable, config.renderMode]);

  // 컬럼 토글 (현재 테이블 컬럼 - 입력용)
  const toggleInputColumn = (column: ColumnOption) => {
    const existingIndex = config.columns.findIndex(
      (c) => c.key === column.columnName && !c.isJoinColumn && !c.isSourceDisplay,
    );
    if (existingIndex >= 0) {
      const newColumns = config.columns.filter((_, i) => i !== existingIndex);
      updateConfig({ columns: newColumns });
    } else {
      // 컬럼의 inputType과 detailSettings 정보 포함
      const newColumn: RepeaterColumnConfig = {
        key: column.columnName,
        title: column.displayName,
        width: "auto",
        visible: true,
        editable: true,
        inputType: column.inputType || "text",
        detailSettings: column.detailSettings
          ? {
              codeGroup: column.detailSettings.codeGroup,
              referenceTable: column.detailSettings.referenceTable,
              referenceColumn: column.detailSettings.referenceColumn,
              displayColumn: column.detailSettings.displayColumn,
              format: column.detailSettings.format,
            }
          : undefined,
      };
      updateConfig({ columns: [...config.columns, newColumn] });
    }
  };

  // 🆕 소스 컬럼 토글 - columns 배열에 isSourceDisplay: true로 추가
  const toggleSourceDisplayColumn = (column: ColumnOption) => {
    const exists = config.columns.some((c) => c.key === column.columnName && c.isSourceDisplay);

    if (exists) {
      // 제거
      updateConfig({ columns: config.columns.filter((c) => c.key !== column.columnName) });
    } else {
      // 추가 (isSourceDisplay: true)
      const newColumn: RepeaterColumnConfig = {
        key: column.columnName,
        title: column.displayName,
        width: "auto",
        visible: true,
        editable: false, // 소스 표시 컬럼은 편집 불가
        isSourceDisplay: true,
      };
      updateConfig({ columns: [...config.columns, newColumn] });
    }
  };

  const isColumnAdded = (columnName: string) => {
    return config.columns.some((c) => c.key === columnName && !c.isSourceDisplay && !c.isJoinColumn);
  };

  const isSourceColumnSelected = (columnName: string) => {
    return config.columns.some((c) => c.key === columnName && c.isSourceDisplay);
  };

  // 컬럼 속성 업데이트
  const updateColumnProp = (key: string, field: keyof RepeaterColumnConfig, value: any) => {
    const newColumns = config.columns.map((col) => (col.key === key ? { ...col, [field]: value } : col));
    updateConfig({ columns: newColumns });
  };

  // 계산 규칙을 config에 반영하는 헬퍼
  const syncCalculationRules = (rules: CalculationRule[]) => {
    setCalculationRules(rules);
    updateConfig({ calculationRules: rules });
  };

  // 계산 규칙 추가
  const addCalculationRule = () => {
    const newRules = [...calculationRules, { id: `calc_${Date.now()}`, targetColumn: "", formula: "" }];
    syncCalculationRules(newRules);
  };

  // 계산 규칙 삭제
  const removeCalculationRule = (id: string) => {
    syncCalculationRules(calculationRules.filter((r) => r.id !== id));
  };

  // 계산 규칙 업데이트
  const updateCalculationRule = (id: string, field: keyof CalculationRule, value: string) => {
    syncCalculationRules(calculationRules.map((r) => (r.id === id ? { ...r, [field]: value } : r)));
  };

  // 수식 입력 필드에 컬럼명 삽입
  const insertColumnToFormula = (ruleId: string, columnKey: string) => {
    const rule = calculationRules.find((r) => r.id === ruleId);
    if (!rule) return;
    const newFormula = rule.formula ? `${rule.formula} ${columnKey}` : columnKey;
    updateCalculationRule(ruleId, "formula", newFormula);
  };

  // 수식의 영어 컬럼명을 한글 제목으로 변환
  const formulaToKorean = (formula: string): string => {
    if (!formula) return "";
    let result = formula;
    const allCols = config.columns || [];
    // 긴 컬럼명부터 치환 (부분 매칭 방지)
    const sorted = [...allCols].sort((a, b) => b.key.length - a.key.length);
    for (const col of sorted) {
      if (col.title && col.key) {
        result = result.replace(new RegExp(`\\b${col.key}\\b`, "g"), col.title);
      }
    }
    return result;
  };

  // 엔티티 컬럼 선택 시 소스 테이블 자동 설정
  const handleEntityColumnSelect = (columnName: string) => {
    const selectedEntity = entityColumns.find((c) => c.columnName === columnName);

    if (selectedEntity) {
      console.log("엔티티 컬럼 선택:", selectedEntity);

      // 소스 테이블 컬럼에서 라벨 정보 찾기
      const displayColInfo = sourceTableColumns.find((c) => c.columnName === selectedEntity.displayColumn);
      const displayLabel = displayColInfo?.displayName || selectedEntity.displayColumn || "";

      updateConfig({
        dataSource: {
          ...config.dataSource,
          sourceTable: selectedEntity.referenceTable || "",
          foreignKey: selectedEntity.columnName,
          referenceKey: selectedEntity.referenceColumn || "id",
          displayColumn: selectedEntity.displayColumn,
        },
        modal: {
          ...config.modal,
          searchFields: selectedEntity.displayColumn ? [selectedEntity.displayColumn] : [],
          sourceDisplayColumns: selectedEntity.displayColumn
            ? [{ key: selectedEntity.displayColumn, label: displayLabel }]
            : [],
        } as V2RepeaterConfig["modal"],
      });
    }
  };

  // 모드 여부
  const isInlineMode = config.renderMode === "inline";
  const isModalMode = config.renderMode === "modal";

  // 엔티티 컬럼 제외한 입력 가능 컬럼 (FK 컬럼 제외)
  const inputableColumns = useMemo(() => {
    const fkColumn = config.dataSource?.foreignKey;
    return currentTableColumns.filter(
      (col) =>
        col.columnName !== fkColumn && // FK 컬럼 제외
        col.inputType !== "entity", // 다른 엔티티 컬럼도 제외 (필요시)
    );
  }, [currentTableColumns, config.dataSource?.foreignKey]);

  return (
    <div className="space-y-4">
      <Tabs defaultValue="basic" className="w-full">
        <TabsList className="grid w-full grid-cols-2">
          <TabsTrigger value="basic" className="text-xs">
            기본
          </TabsTrigger>
          <TabsTrigger value="columns" className="text-xs">
            컬럼
          </TabsTrigger>
        </TabsList>

        {/* 기본 설정 탭 */}
        <TabsContent value="basic" className="mt-4 space-y-4">
          {/* 렌더링 모드 - 카드 선택 */}
          <div className="space-y-2">
            <p className="text-sm font-medium">리피터를 어떤 방식으로 사용하나요?</p>
            <div className="grid grid-cols-3 gap-2">
              {[
                { value: "inline", icon: Rows3, title: "직접 입력", description: "테이블 컬럼에 바로 입력해요" },
                { value: "modal", icon: Columns3, title: "모달 선택", description: "엔티티를 검색해서 추가해요" },
                {
                  value: "button",
                  icon: MousePointerClick,
                  title: "버튼 연결",
                  description: "버튼으로 관련 화면을 열어요",
                },
              ].map((card) => {
                const Icon = card.icon;
                const isSelected = config.renderMode === card.value;
                return (
                  <button
                    key={card.value}
                    type="button"
                    onClick={() => {
                      const newMode = card.value as any;
                      const currentMode = config.renderMode;
                      if (currentMode === "modal" && newMode === "inline") {
                        const filteredColumns = config.columns.filter((col) => !col.isSourceDisplay);
                        updateConfig({
                          renderMode: newMode,
                          columns: filteredColumns,
                          dataSource: {
                            ...config.dataSource,
                            sourceTable: undefined,
                            foreignKey: undefined,
                            referenceKey: undefined,
                            displayColumn: undefined,
                          },
                          modal: {
                            ...config.modal,
                            searchFields: [],
                            sourceDisplayColumns: [],
                          } as V2RepeaterConfig["modal"],
                        });
                      } else {
                        updateConfig({ renderMode: newMode });
                      }
                    }}
                    className={cn(
                      "flex min-h-[80px] flex-col items-center justify-center rounded-lg border p-3 text-center transition-all",
                      isSelected
                        ? "border-primary bg-primary/5 ring-primary/20 ring-1"
                        : "border-border hover:border-primary/50 hover:bg-muted/50",
                    )}
                  >
                    <Icon className="text-primary mb-1.5 h-5 w-5" />
                    <span className="text-xs leading-tight font-medium">{card.title}</span>
                    <span className="text-muted-foreground mt-0.5 text-[10px] leading-tight">{card.description}</span>
                  </button>
                );
              })}
            </div>
          </div>

          {/* 저장 대상 테이블 */}
          <div className="bg-muted/30 space-y-3 rounded-lg border p-4">
            <div className="flex items-center gap-2">
              <Database className="text-primary h-4 w-4" />
              <span className="text-sm font-medium">데이터를 어디에 저장하나요?</span>
            </div>

            {/* 현재 선택된 테이블 표시 (기존 테이블 UI와 동일한 스타일) */}
            <div
              className={cn(
                "rounded-lg border p-3",
                config.useCustomTable && config.mainTableName
                  ? "border-orange-300 bg-amber-50"
                  : "border-primary/40 bg-primary/10",
              )}
            >
              <div className="flex items-center gap-2">
                <Database
                  className={cn(
                    "h-4 w-4",
                    config.useCustomTable && config.mainTableName ? "text-amber-600" : "text-primary",
                  )}
                />
                <div className="flex-1">
                  <p
                    className={cn(
                      "text-sm font-medium",
                      config.useCustomTable && config.mainTableName ? "text-orange-700" : "text-primary",
                    )}
                  >
                    {config.useCustomTable && config.mainTableName
                      ? allTables.find((t) => t.tableName === config.mainTableName)?.displayName || config.mainTableName
                      : currentTableName || "미설정"}
                  </p>
                  {config.useCustomTable && config.mainTableName && config.foreignKeyColumn && (
                    <p className="mt-0.5 text-[10px] text-amber-600">
                      FK: {config.foreignKeyColumn} → {currentTableName}.{config.foreignKeySourceColumn || "id"}
                    </p>
                  )}
                  {!config.useCustomTable && currentTableName && (
                    <p className="text-primary mt-0.5 text-[10px]">화면 메인 테이블</p>
                  )}
                </div>
              </div>
            </div>

            {/* 테이블 변경 Combobox */}
            <Popover open={tableComboboxOpen} onOpenChange={setTableComboboxOpen}>
              <PopoverTrigger asChild>
                <Button
                  variant="outline"
                  role="combobox"
                  aria-expanded={tableComboboxOpen}
                  disabled={loadingTables || loadingRelations}
                  className="h-8 w-full justify-between text-xs"
                >
                  {loadingTables ? "로딩 중..." : "다른 테이블 선택..."}
                  <ChevronsUpDown className="ml-2 h-3 w-3 shrink-0 opacity-50" />
                </Button>
              </PopoverTrigger>
              <PopoverContent className="p-0" style={{ width: "var(--radix-popover-trigger-width)" }} align="start">
                <Command>
                  <CommandInput placeholder="테이블 검색..." className="text-xs" />
                  <CommandList className="max-h-60">
                    <CommandEmpty className="py-3 text-center text-xs">테이블을 찾을 수 없습니다.</CommandEmpty>

                    {/* 현재 테이블 (기본) */}
                    {currentTableName && (
                      <CommandGroup heading="기본">
                        <CommandItem
                          value={currentTableName}
                          onSelect={() => {
                            handleSaveTableSelect(currentTableName);
                            setTableComboboxOpen(false);
                          }}
                          className="text-xs"
                        >
                          <Check
                            className={cn(
                              "mr-2 h-3 w-3",
                              !config.useCustomTable || !config.mainTableName ? "opacity-100" : "opacity-0",
                            )}
                          />
                          <Database className="text-primary mr-2 h-3 w-3" />
                          <span>{currentTableName}</span>
                          <span className="text-muted-foreground ml-1 text-[10px]">(기본)</span>
                        </CommandItem>
                      </CommandGroup>
                    )}

                    {/* 연관 테이블 (엔티티 관계) */}
                    {relatedTables.length > 0 && (
                      <CommandGroup heading="연관 테이블 (FK 자동 설정)">
                        {relatedTables.map((rel) => (
                          <CommandItem
                            key={rel.tableName}
                            value={`${rel.tableName} ${rel.tableLabel}`}
                            onSelect={() => {
                              handleSaveTableSelect(rel.tableName);
                              setTableComboboxOpen(false);
                            }}
                            className="text-xs"
                          >
                            <Check
                              className={cn(
                                "mr-2 h-3 w-3",
                                config.mainTableName === rel.tableName ? "opacity-100" : "opacity-0",
                              )}
                            />
                            <Link2 className="mr-2 h-3 w-3 text-amber-500" />
                            <span>{rel.tableLabel}</span>
                            <span className="text-muted-foreground ml-1 text-[10px]">({rel.foreignKeyColumn})</span>
                          </CommandItem>
                        ))}
                      </CommandGroup>
                    )}

                    {/* 전체 테이블 목록 */}
                    <CommandGroup heading="전체 테이블 (FK 직접 입력)">
                      {allTables
                        .filter(
                          (t) =>
                            t.tableName !== currentTableName && !relatedTables.some((r) => r.tableName === t.tableName),
                        )
                        .map((table) => (
                          <CommandItem
                            key={table.tableName}
                            value={`${table.tableName} ${table.displayName}`}
                            onSelect={() => {
                              handleSaveTableSelect(table.tableName);
                              setTableComboboxOpen(false);
                            }}
                            className="text-xs"
                          >
                            <Check
                              className={cn(
                                "mr-2 h-3 w-3",
                                config.mainTableName === table.tableName ? "opacity-100" : "opacity-0",
                              )}
                            />
                            <Database className="text-muted-foreground/70 mr-2 h-3 w-3" />
                            <span>{table.displayName}</span>
                          </CommandItem>
                        ))}
                    </CommandGroup>
                  </CommandList>
                </Command>
              </PopoverContent>
            </Popover>

            {/* FK 직접 입력 - 화면 메인 테이블이 있고 연관 테이블이 아닌 경우만 표시 */}
            {/* 화면 메인 테이블이 없으면 FK 설정 불필요 (독립 저장) */}
            {config.useCustomTable &&
              config.mainTableName &&
              currentTableName &&
              !relatedTables.some((r) => r.tableName === config.mainTableName) && (
                <div className="space-y-2 rounded border border-amber-200 bg-amber-50 p-2">
                  <p className="text-[10px] text-amber-700">
                    화면 테이블({currentTableName})과의 엔티티 관계가 없습니다. FK 컬럼을 직접 입력하세요.
                  </p>
                  <div className="grid grid-cols-2 gap-2">
                    <div className="space-y-1">
                      <Label className="text-[10px]">FK 컬럼 (저장 테이블)</Label>
                      <Input
                        value={config.foreignKeyColumn || ""}
                        onChange={(e) => updateConfig({ foreignKeyColumn: e.target.value })}
                        placeholder="예: master_id"
                        className="h-7 text-xs"
                      />
                    </div>
                    <div className="space-y-1">
                      <Label className="text-[10px]">PK 컬럼 (화면 테이블)</Label>
                      <Input
                        value={config.foreignKeySourceColumn || "id"}
                        onChange={(e) => updateConfig({ foreignKeySourceColumn: e.target.value })}
                        placeholder="id"
                        className="h-7 text-xs"
                      />
                    </div>
                  </div>
                </div>
              )}

            {/* 화면 메인 테이블이 없을 때 안내 */}
            {config.useCustomTable && config.mainTableName && !currentTableName && (
              <div className="border-primary/20 bg-primary/10 rounded border p-2">
                <p className="text-primary text-[10px]">독립 저장 모드: 화면 테이블 없이 직접 저장해요</p>
              </div>
            )}

            {/* 현재 화면 정보 (메인 테이블이 설정된 경우에만 표시) */}
            {currentTableName && (
              <div className="bg-background rounded-md border p-3">
                <p className="text-muted-foreground text-xs">화면 메인 테이블</p>
                <p className="mt-0.5 text-sm font-medium">{currentTableName}</p>
                <p className="text-muted-foreground mt-0.5 text-[10px]">
                  컬럼 {currentTableColumns.length}개 / 엔티티 {entityColumns.length}개
                </p>
              </div>
            )}
          </div>

          {/* 모달 모드: 엔티티 컬럼 선택 */}
          {isModalMode && (
            <>
              <div className="bg-muted/30 space-y-3 rounded-lg border p-4">
                <div className="flex items-center gap-2">
                  <Link2 className="text-primary h-4 w-4" />
                  <span className="text-sm font-medium">어떤 엔티티를 검색하나요?</span>
                </div>
                <p className="text-muted-foreground text-[11px]">모달에서 검색할 엔티티를 선택하면 FK만 저장돼요</p>

                {entityColumns.length > 0 ? (
                  <Select
                    value={config.dataSource?.foreignKey || ""}
                    onValueChange={handleEntityColumnSelect}
                    disabled={!targetTableForColumns}
                  >
                    <SelectTrigger className="h-7 text-xs">
                      <SelectValue placeholder="엔티티 컬럼 선택" />
                    </SelectTrigger>
                    <SelectContent>
                      {entityColumns.map((col) => (
                        <SelectItem key={col.columnName} value={col.columnName}>
                          <div className="flex items-center gap-2">
                            <Link2 className="text-primary h-3 w-3" />
                            <span>{col.displayName}</span>
                            <ArrowRight className="text-muted-foreground/70 h-3 w-3" />
                            <span className="text-muted-foreground">{col.referenceTable}</span>
                          </div>
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                ) : (
                  <div className="rounded-md border-2 border-dashed p-4 text-center">
                    <p className="text-muted-foreground text-sm">
                      {loadingColumns
                        ? "컬럼 정보를 불러오고 있어요..."
                        : !targetTableForColumns
                          ? "저장 테이블을 먼저 선택해주세요"
                          : "엔티티 타입 컬럼이 없어요"}
                    </p>
                  </div>
                )}

                {/* 선택된 엔티티 정보 */}
                {config.dataSource?.sourceTable && (
                  <div className="bg-background space-y-1 rounded-md border p-3">
                    <p className="text-muted-foreground text-xs">선택된 엔티티</p>
                    <p className="text-sm font-medium">{config.dataSource.sourceTable}</p>
                    <p className="text-muted-foreground text-[11px]">
                      {config.dataSource.foreignKey} 컬럼에 FK로 저장돼요
                    </p>
                  </div>
                )}
              </div>

              {/* 모달 표시 설정 */}
              <div className="bg-muted/30 space-y-3 rounded-lg border p-4">
                <span className="text-sm font-medium">모달 표시 설정</span>
                <div className="space-y-2">
                  <div className="space-y-1">
                    <Label className="text-muted-foreground text-[10px]">모달 제목</Label>
                    <Input
                      value={config.modal?.title || ""}
                      onChange={(e) => updateModal("title", e.target.value)}
                      placeholder="항목 검색"
                      className="h-7 text-xs"
                    />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-muted-foreground text-[10px]">검색 버튼 텍스트</Label>
                    <Input
                      value={config.modal?.buttonText || ""}
                      onChange={(e) => updateModal("buttonText", e.target.value)}
                      placeholder="검색"
                      className="h-7 text-xs"
                    />
                  </div>
                </div>
              </div>
            </>
          )}

          {/* 기능 옵션 - Collapsible */}
          <Collapsible open={featureOptionsOpen} onOpenChange={setFeatureOptionsOpen}>
            <CollapsibleTrigger asChild>
              <button
                type="button"
                className="bg-muted/30 hover:bg-muted/50 flex w-full items-center justify-between rounded-lg border px-4 py-2.5 text-left transition-colors"
              >
                <div className="flex items-center gap-2">
                  <Settings className="text-muted-foreground h-4 w-4" />
                  <span className="text-sm font-medium">기능 옵션</span>
                  <Badge variant="secondary" className="h-5 text-[10px]">
                    6개
                  </Badge>
                </div>
                <ChevronDown
                  className={cn(
                    "text-muted-foreground h-4 w-4 transition-transform duration-200",
                    featureOptionsOpen && "rotate-180",
                  )}
                />
              </button>
            </CollapsibleTrigger>
            <CollapsibleContent>
              <div className="space-y-1 rounded-b-lg border border-t-0 p-3">
                <div className="flex items-center justify-between py-1">
                  <div>
                    <p className="text-sm">추가 버튼</p>
                    <p className="text-muted-foreground text-[11px]">새로운 행을 추가할 수 있어요</p>
                  </div>
                  <Switch
                    checked={config.features?.showAddButton ?? true}
                    onCheckedChange={(checked) => updateFeatures("showAddButton", checked)}
                  />
                </div>
                <div className="flex items-center justify-between py-1">
                  <div>
                    <p className="text-sm">삭제 버튼</p>
                    <p className="text-muted-foreground text-[11px]">선택한 행을 삭제할 수 있어요</p>
                  </div>
                  <Switch
                    checked={config.features?.showDeleteButton ?? true}
                    onCheckedChange={(checked) => updateFeatures("showDeleteButton", checked)}
                  />
                </div>
                <div className="flex items-center justify-between py-1">
                  <div>
                    <p className="text-sm">인라인 편집</p>
                    <p className="text-muted-foreground text-[11px]">셀을 클릭하면 바로 수정할 수 있어요</p>
                  </div>
                  <Switch
                    checked={config.features?.inlineEdit ?? false}
                    onCheckedChange={(checked) => updateFeatures("inlineEdit", checked)}
                  />
                </div>
                <div className="flex items-center justify-between py-1">
                  <div>
                    <p className="text-sm">다중 선택</p>
                    <p className="text-muted-foreground text-[11px]">여러 행을 동시에 선택할 수 있어요</p>
                  </div>
                  <Switch
                    checked={config.features?.multiSelect ?? true}
                    onCheckedChange={(checked) => updateFeatures("multiSelect", checked)}
                  />
                </div>
                <div className="flex items-center justify-between py-1">
                  <div>
                    <p className="text-sm">행 번호</p>
                    <p className="text-muted-foreground text-[11px]">각 행에 순번을 표시해요</p>
                  </div>
                  <Switch
                    checked={config.features?.showRowNumber ?? false}
                    onCheckedChange={(checked) => updateFeatures("showRowNumber", checked)}
                  />
                </div>
                <div className="flex items-center justify-between py-1">
                  <div>
                    <p className="text-sm">행 선택</p>
                    <p className="text-muted-foreground text-[11px]">체크박스로 행을 선택할 수 있어요</p>
                  </div>
                  <Switch
                    checked={config.features?.selectable ?? false}
                    onCheckedChange={(checked) => updateFeatures("selectable", checked)}
                  />
                </div>
              </div>
            </CollapsibleContent>
          </Collapsible>

          {/* 고급 설정 - Collapsible (소스 디테일 등) */}
          <Collapsible>
            <CollapsibleTrigger asChild>
              <button
                type="button"
                className="bg-muted/30 hover:bg-muted/50 flex w-full items-center justify-between rounded-lg border px-4 py-2.5 text-left transition-colors"
              >
                <div className="flex items-center gap-2">
                  <Settings className="text-muted-foreground h-4 w-4" />
                  <span className="text-sm font-medium">고급 설정</span>
                </div>
                <ChevronDown className="text-muted-foreground h-4 w-4 transition-transform duration-200" />
              </button>
            </CollapsibleTrigger>
            <CollapsibleContent>
              <div className="space-y-3 rounded-b-lg border border-t-0 p-4">
                {/* 소스 디테일 자동 조회 */}
                <div className="flex items-center justify-between py-1">
                  <div>
                    <p className="text-sm">소스 디테일 자동 조회</p>
                    <p className="text-muted-foreground text-[11px]">마스터 데이터의 디테일 행을 자동으로 채워요</p>
                  </div>
                  <Switch
                    checked={!!config.sourceDetailConfig}
                    onCheckedChange={(checked) => {
                      if (checked) {
                        updateConfig({
                          sourceDetailConfig: {
                            tableName: "",
                            foreignKey: "",
                            parentKey: "",
                          },
                        });
                      } else {
                        updateConfig({ sourceDetailConfig: undefined });
                      }
                    }}
                  />
                </div>

                {config.sourceDetailConfig && (
                  <div className="border-primary/20 ml-4 space-y-2 border-l-2 pl-3">
                    <div className="space-y-1">
                      <p className="text-muted-foreground text-xs">디테일 테이블</p>
                      <Popover>
                        <PopoverTrigger asChild>
                          <Button variant="outline" role="combobox" className="h-7 w-full justify-between text-xs">
                            {config.sourceDetailConfig.tableName
                              ? allTables.find((t) => t.tableName === config.sourceDetailConfig!.tableName)
                                  ?.displayName || config.sourceDetailConfig.tableName
                              : "테이블 선택..."}
                            <ChevronsUpDown className="ml-2 h-3 w-3 shrink-0 opacity-50" />
                          </Button>
                        </PopoverTrigger>
                        <PopoverContent
                          className="p-0"
                          style={{ width: "var(--radix-popover-trigger-width)" }}
                          align="start"
                        >
                          <Command>
                            <CommandInput placeholder="테이블 검색..." className="text-xs" />
                            <CommandList className="max-h-48">
                              <CommandEmpty className="py-3 text-center text-xs">
                                테이블을 찾을 수 없습니다.
                              </CommandEmpty>
                              <CommandGroup>
                                {allTables.map((table) => (
                                  <CommandItem
                                    key={table.tableName}
                                    value={`${table.tableName} ${table.displayName}`}
                                    onSelect={() => {
                                      updateConfig({
                                        sourceDetailConfig: {
                                          ...config.sourceDetailConfig!,
                                          tableName: table.tableName,
                                        },
                                      });
                                    }}
                                    className="text-xs"
                                  >
                                    <Check
                                      className={cn(
                                        "mr-2 h-3 w-3",
                                        config.sourceDetailConfig!.tableName === table.tableName
                                          ? "opacity-100"
                                          : "opacity-0",
                                      )}
                                    />
                                    <span>{table.displayName}</span>
                                  </CommandItem>
                                ))}
                              </CommandGroup>
                            </CommandList>
                          </Command>
                        </PopoverContent>
                      </Popover>
                    </div>

                    <div className="grid grid-cols-2 gap-2">
                      <div className="space-y-1">
                        <p className="text-muted-foreground text-xs">디테일 FK 컬럼</p>
                        <Input
                          value={config.sourceDetailConfig.foreignKey || ""}
                          onChange={(e) =>
                            updateConfig({
                              sourceDetailConfig: {
                                ...config.sourceDetailConfig!,
                                foreignKey: e.target.value,
                              },
                            })
                          }
                          placeholder="예: order_no"
                          className="h-7 text-xs"
                        />
                      </div>
                      <div className="space-y-1">
                        <p className="text-muted-foreground text-xs">마스터 키 컬럼</p>
                        <Input
                          value={config.sourceDetailConfig.parentKey || ""}
                          onChange={(e) =>
                            updateConfig({
                              sourceDetailConfig: {
                                ...config.sourceDetailConfig!,
                                parentKey: e.target.value,
                              },
                            })
                          }
                          placeholder="예: order_no"
                          className="h-7 text-xs"
                        />
                      </div>
                    </div>

                    <p className="text-muted-foreground text-[11px]">
                      마스터에서 [{config.sourceDetailConfig.parentKey || "?"}] 추출 →{" "}
                      {config.sourceDetailConfig.tableName || "?"}.{config.sourceDetailConfig.foreignKey || "?"} 로
                      조회해요
                    </p>
                  </div>
                )}
              </div>
            </CollapsibleContent>
          </Collapsible>
        </TabsContent>

        {/* 컬럼 설정 탭 */}
        <TabsContent value="columns" className="mt-4 space-y-4">
          {/* 통합 컬럼 선택 - Collapsible */}
          <Collapsible open={columnSelectOpen} onOpenChange={setColumnSelectOpen}>
            <CollapsibleTrigger asChild>
              <button
                type="button"
                className="bg-muted/30 hover:bg-muted/50 flex w-full items-center justify-between rounded-lg border px-4 py-2.5 text-left transition-colors"
              >
                <div className="flex items-center gap-2">
                  <Database className="text-muted-foreground h-4 w-4" />
                  <span className="truncate text-sm font-medium">{isModalMode ? "컬럼 표시/입력" : "입력 컬럼"}</span>
                  <Badge variant="secondary" className="h-5 text-[10px]">
                    {inputableColumns.length}개 컬럼
                  </Badge>
                </div>
                <ChevronDown
                  className={cn(
                    "text-muted-foreground h-4 w-4 transition-transform duration-200",
                    columnSelectOpen && "rotate-180",
                  )}
                />
              </button>
            </CollapsibleTrigger>
            <CollapsibleContent>
              <div className="space-y-3 rounded-b-lg border border-t-0 p-3">
                <p className="text-muted-foreground text-[11px]">
                  {isModalMode
                    ? "소스 테이블 컬럼은 표시용, 저장 테이블 컬럼은 입력용이에요"
                    : "체크한 컬럼이 리피터에 입력 필드로 표시돼요"}
                </p>

                {/* 모달 모드: 소스 테이블 컬럼 (표시용) */}
                {isModalMode && config.dataSource?.sourceTable && (
                  <>
                    <div className="text-primary mt-2 mb-1 flex items-center gap-1 text-[10px] font-medium">
                      <Link2 className="h-3 w-3" />
                      <span className="truncate">소스 테이블 ({config.dataSource.sourceTable}) - 표시용</span>
                    </div>
                    {loadingSourceColumns ? (
                      <p className="text-muted-foreground py-2 text-xs">로딩 중...</p>
                    ) : sourceTableColumns.length === 0 ? (
                      <p className="text-muted-foreground py-2 text-xs">컬럼 정보가 없습니다</p>
                    ) : (
                      <div className="border-primary/20 bg-primary/10/30 space-y-0.5 rounded-md border p-2">
                        {sourceTableColumns.map((column) => (
                          <div
                            key={`source-${column.columnName}`}
                            className={cn(
                              "hover:bg-primary/10/50 flex cursor-pointer items-center gap-2 rounded px-2 py-1",
                              isSourceColumnSelected(column.columnName) && "bg-primary/10",
                            )}
                            onClick={() => toggleSourceDisplayColumn(column)}
                          >
                            <Checkbox
                              checked={isSourceColumnSelected(column.columnName)}
                              onCheckedChange={() => toggleSourceDisplayColumn(column)}
                              className="pointer-events-none h-3.5 w-3.5"
                            />
                            <Link2 className="text-primary h-3 w-3 flex-shrink-0" />
                            <span className="truncate text-xs">{column.displayName}</span>
                            <span className="text-primary/80 ml-auto text-[10px]">표시</span>
                          </div>
                        ))}
                      </div>
                    )}
                  </>
                )}

                {/* 저장 테이블 컬럼 (입력용) */}
                <div className="text-muted-foreground mt-3 mb-1 flex items-center gap-1 text-[10px] font-medium">
                  <Database className="h-3 w-3" />
                  <span className="truncate">저장 테이블 ({targetTableForColumns || "미선택"}) - 입력용</span>
                </div>
                {loadingColumns ? (
                  <p className="text-muted-foreground py-2 text-xs">로딩 중...</p>
                ) : inputableColumns.length === 0 ? (
                  <p className="text-muted-foreground py-2 text-xs">컬럼 정보가 없습니다</p>
                ) : (
                  <div className="space-y-0.5 rounded-md border p-2">
                    {inputableColumns.map((column) => (
                      <div
                        key={`input-${column.columnName}`}
                        className={cn(
                          "hover:bg-muted/50 flex cursor-pointer items-center gap-2 rounded px-2 py-1",
                          isColumnAdded(column.columnName) && "bg-primary/10",
                        )}
                        onClick={() => toggleInputColumn(column)}
                      >
                        <Checkbox
                          checked={isColumnAdded(column.columnName)}
                          onCheckedChange={() => toggleInputColumn(column)}
                          className="pointer-events-none h-3.5 w-3.5"
                        />
                        <Database className="text-muted-foreground h-3 w-3 flex-shrink-0" />
                        <span className="truncate text-xs">{column.displayName}</span>
                        <span className="text-muted-foreground/70 ml-auto text-[10px]">{column.inputType}</span>
                      </div>
                    ))}
                  </div>
                )}
              </div>

              {/* ===== 🆕 Entity 조인 컬럼 (표시용) ===== */}
              <div className="mt-4 space-y-2">
                <div className="flex items-center gap-2">
                  <Link2 className="text-primary h-4 w-4" />
                  <Label className="text-primary text-xs font-medium">Entity 조인 컬럼 (읽기전용)</Label>
                </div>
                <p className="text-muted-foreground text-[10px]">
                  FK 컬럼을 기반으로 참조 테이블의 데이터를 자동으로 조회하여 표시합니다.
                </p>

                {loadingEntityJoins ? (
                  <p className="text-muted-foreground py-2 text-xs">로딩 중...</p>
                ) : entityJoinData.joinTables.length === 0 ? (
                  <p className="text-muted-foreground py-2 text-xs">
                    {entityJoinTargetTable
                      ? `${entityJoinTargetTable} 테이블에 Entity 조인 가능한 컬럼이 없습니다`
                      : "저장 테이블을 먼저 설정해주세요"}
                  </p>
                ) : (
                  <div className="space-y-3">
                    {entityJoinData.joinTables.map((joinTable, tableIndex) => {
                      const sourceColumn = (joinTable as any).joinConfig?.sourceColumn || "";

                      return (
                        <div key={tableIndex} className="space-y-1">
                          <div className="text-primary mb-1 flex items-center gap-2 text-[10px] font-medium">
                            <Link2 className="h-3 w-3" />
                            <span>{joinTable.tableName}</span>
                            <span className="text-muted-foreground">({sourceColumn})</span>
                          </div>
                          <div className="border-primary/20 bg-primary/10/30 max-h-40 space-y-0.5 overflow-y-auto rounded-md border p-2">
                            {joinTable.availableColumns.map((column, colIndex) => {
                              const isActive = isEntityJoinColumnActive(
                                joinTable.tableName,
                                sourceColumn,
                                column.columnName,
                              );
                              const matchingCol = config.columns.find(
                                (c) => c.key === column.columnName && c.isJoinColumn,
                              );
                              const displayField = matchingCol?.key || column.columnName;

                              return (
                                <div
                                  key={colIndex}
                                  className={cn(
                                    "hover:bg-primary/10/50 flex cursor-pointer items-center gap-2 rounded px-2 py-1",
                                    isActive && "bg-primary/10",
                                  )}
                                  onClick={() =>
                                    toggleEntityJoinColumn(
                                      joinTable.tableName,
                                      sourceColumn,
                                      column.columnName,
                                      column.columnLabel,
                                      displayField,
                                      column.inputType || column.dataType,
                                    )
                                  }
                                >
                                  <Checkbox checked={isActive} className="pointer-events-none h-3.5 w-3.5" />
                                  <Link2 className="text-primary h-3 w-3 flex-shrink-0" />
                                  <span className="truncate text-xs">{column.columnLabel}</span>
                                  <span className="text-primary/80 ml-auto text-[10px]">
                                    {column.inputType || column.dataType}
                                  </span>
                                </div>
                              );
                            })}
                          </div>
                        </div>
                      );
                    })}
                  </div>
                )}
              </div>
            </CollapsibleContent>
          </Collapsible>

          {/* 선택된 컬럼 상세 설정 - Collapsible */}
          {config.columns.length > 0 && (
            <Collapsible open={selectedColumnsOpen} onOpenChange={setSelectedColumnsOpen}>
              <CollapsibleTrigger asChild>
                <button
                  type="button"
                  className="bg-muted/30 hover:bg-muted/50 flex w-full items-center justify-between rounded-lg border px-4 py-2.5 text-left transition-colors"
                >
                  <div className="flex items-center gap-2">
                    <GripVertical className="text-muted-foreground h-4 w-4" />
                    <span className="text-sm font-medium">선택된 컬럼</span>
                    <Badge variant="secondary" className="h-5 text-[10px]">
                      {config.columns.length}개
                    </Badge>
                  </div>
                  <ChevronDown
                    className={cn(
                      "text-muted-foreground h-4 w-4 transition-transform duration-200",
                      selectedColumnsOpen && "rotate-180",
                    )}
                  />
                </button>
              </CollapsibleTrigger>
              <CollapsibleContent>
                <div className="space-y-3 rounded-b-lg border border-t-0 p-3">
                  <p className="text-muted-foreground text-[10px]">드래그로 순서 변경, 클릭하여 상세 설정</p>
                  <div className="space-y-1">
                    {config.columns.map((col, index) => (
                      <div key={col.key} className="space-y-1">
                        {/* 컬럼 헤더 (드래그 가능) */}
                        <div
                          className={cn(
                            "flex items-center gap-2 rounded-md border p-2",
                            col.isSourceDisplay || col.isJoinColumn
                              ? "border-primary/20 bg-primary/10/50"
                              : "border-border bg-muted/30",
                            col.hidden && "opacity-50",
                          )}
                          draggable
                          onDragStart={(e) => {
                            e.dataTransfer.setData("columnIndex", String(index));
                          }}
                          onDragOver={(e) => e.preventDefault()}
                          onDrop={(e) => {
                            e.preventDefault();
                            const fromIndex = parseInt(e.dataTransfer.getData("columnIndex"), 10);
                            if (fromIndex !== index) {
                              const newColumns = [...config.columns];
                              const [movedCol] = newColumns.splice(fromIndex, 1);
                              newColumns.splice(index, 0, movedCol);
                              updateConfig({ columns: newColumns });
                            }
                          }}
                        >
                          <GripVertical className="text-muted-foreground h-3 w-3 flex-shrink-0 cursor-grab" />

                          {/* 확장/축소 버튼 (입력 컬럼만) */}
                          {!col.isSourceDisplay && !col.isJoinColumn && (
                            <button
                              type="button"
                              onClick={() => setExpandedColumn(expandedColumn === col.key ? null : col.key)}
                              className="hover:bg-muted/80 rounded p-0.5"
                            >
                              {expandedColumn === col.key ? (
                                <ChevronDown className="text-muted-foreground h-3 w-3" />
                              ) : (
                                <ChevronRight className="text-muted-foreground h-3 w-3" />
                              )}
                            </button>
                          )}

                          {col.isSourceDisplay ? (
                            <Link2 className="text-primary h-3 w-3 flex-shrink-0" aria-label="소스 표시 (읽기 전용)" />
                          ) : (
                            <Database className="text-muted-foreground h-3 w-3 flex-shrink-0" />
                          )}

                          <Input
                            value={col.title}
                            onChange={(e) => updateColumnProp(col.key, "title", e.target.value)}
                            placeholder="제목"
                            className="h-6 flex-1 text-xs"
                          />

                          {/* 히든 토글 (입력 컬럼만) */}
                          {!col.isSourceDisplay && !col.isJoinColumn && (
                            <button
                              type="button"
                              onClick={() => updateColumnProp(col.key, "hidden", !col.hidden)}
                              className={cn(
                                "hover:bg-muted/80 rounded p-1",
                                col.hidden ? "text-muted-foreground/70" : "text-muted-foreground",
                              )}
                              title={col.hidden ? "히든 (저장만 됨)" : "표시됨"}
                            >
                              {col.hidden ? <EyeOff className="h-3 w-3" /> : <Eye className="h-3 w-3" />}
                            </button>
                          )}

                          {/* 자동입력 표시 아이콘 */}
                          {!col.isSourceDisplay &&
                            !col.isJoinColumn &&
                            col.autoFill?.type &&
                            col.autoFill.type !== "none" && (
                              <Wand2 className="h-3 w-3 flex-shrink-0 text-purple-500" aria-label="자동 입력" />
                            )}

                          {/* 편집 가능 토글 */}
                          {!col.isSourceDisplay && !col.isJoinColumn && (
                            <button
                              type="button"
                              onClick={() => updateColumnProp(col.key, "editable", !(col.editable ?? true))}
                              className={cn(
                                "shrink-0 rounded px-1.5 py-0.5 text-[9px] font-medium transition-colors",
                                (col.editable ?? true)
                                  ? "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400"
                                  : "bg-muted text-muted-foreground dark:bg-foreground/90 dark:text-muted-foreground/70",
                              )}
                              title={
                                (col.editable ?? true)
                                  ? "편집 가능 (클릭하여 읽기 전용으로 변경)"
                                  : "읽기 전용 (클릭하여 편집 가능으로 변경)"
                              }
                            >
                              {(col.editable ?? true) ? "편집" : "읽기"}
                            </button>
                          )}

                          <Button
                            type="button"
                            variant="ghost"
                            size="sm"
                            onClick={() => {
                              if (col.isSourceDisplay) {
                                toggleSourceDisplayColumn({ columnName: col.key, displayName: col.title });
                              } else if (col.isJoinColumn) {
                                const newColumns = config.columns.filter((c) => c.key !== col.key);
                                const newEntityJoins = config.entityJoins
                                  ?.map((join) => ({
                                    ...join,
                                    columns: join.columns.filter((c) => c.displayField !== col.key),
                                  }))
                                  .filter((join) => join.columns.length > 0);
                                updateConfig({ columns: newColumns, entityJoins: newEntityJoins });
                              } else {
                                toggleInputColumn({ columnName: col.key, displayName: col.title });
                              }
                            }}
                            className="text-destructive h-6 w-6 p-0"
                          >
                            <Trash2 className="h-3 w-3" />
                          </Button>
                        </div>

                        {/* 확장된 상세 설정 (입력 컬럼만) */}
                        {!col.isSourceDisplay && !col.isJoinColumn && expandedColumn === col.key && (
                          <div className="border-input bg-muted ml-6 space-y-2 rounded-md border border-dashed p-2">
                            {/* 자동 입력 설정 */}
                            <div className="space-y-1">
                              <Label className="text-muted-foreground text-[10px]">자동 입력</Label>
                              <Select
                                value={col.autoFill?.type || "none"}
                                onValueChange={(value) => {
                                  const autoFill = value === "none" ? undefined : { type: value as any };
                                  updateColumnProp(col.key, "autoFill", autoFill);
                                }}
                              >
                                <SelectTrigger className="h-7 text-xs">
                                  <SelectValue />
                                </SelectTrigger>
                                <SelectContent>
                                  {autoFillOptions.map((opt) => (
                                    <SelectItem key={opt.value} value={opt.value} className="text-xs">
                                      {opt.label}
                                    </SelectItem>
                                  ))}
                                </SelectContent>
                              </Select>
                            </div>

                            {/* 채번 규칙 선택 */}
                            {col.autoFill?.type === "numbering" && (
                              <div className="space-y-2">
                                {/* 대상 메뉴 선택 */}
                                <div className="space-y-1">
                                  <Label className="text-muted-foreground text-[10px]">
                                    대상 메뉴 선택 <span className="text-destructive">*</span>
                                  </Label>
                                  <Select
                                    value={selectedMenuObjid?.toString() || ""}
                                    onValueChange={(value) => {
                                      const menuObjidNum = parseInt(value);
                                      setSelectedMenuObjid(menuObjidNum);

                                      // 컬럼 설정에도 저장하여 유지
                                      updateColumnProp(col.key, "autoFill", {
                                        ...col.autoFill,
                                        selectedMenuObjid: menuObjidNum,
                                        numberingRuleId: undefined, // 메뉴 변경 시 규칙 초기화
                                      });
                                    }}
                                    disabled={loadingMenus}
                                  >
                                    <SelectTrigger className="h-7 text-xs">
                                      <SelectValue
                                        placeholder={loadingMenus ? "메뉴 로딩 중..." : "채번규칙을 사용할 메뉴 선택"}
                                      />
                                    </SelectTrigger>
                                    <SelectContent>
                                      {parentMenus.length === 0 ? (
                                        <SelectItem value="no-menus" disabled>
                                          사용 가능한 메뉴가 없습니다
                                        </SelectItem>
                                      ) : (
                                        parentMenus.map((menu) => (
                                          <SelectItem key={menu.objid} value={menu.objid.toString()}>
                                            {menu.menu_name_kor}
                                          </SelectItem>
                                        ))
                                      )}
                                    </SelectContent>
                                  </Select>
                                  <p className="text-muted-foreground text-[10px]">
                                    이 입력 필드가 어느 메뉴에 속할지 선택하세요 (해당 메뉴의 채번규칙이 적용됩니다)
                                  </p>
                                </div>

                                {/* 채번 규칙 선택 (메뉴 선택 후) */}
                                {selectedMenuObjid ? (
                                  <div className="space-y-1">
                                    <Label className="text-muted-foreground text-[10px]">
                                      채번 규칙 선택 <span className="text-destructive">*</span>
                                    </Label>
                                    {loadingNumberingRules ? (
                                      <p className="text-muted-foreground/70 text-[10px]">규칙 로딩 중...</p>
                                    ) : numberingRules.length === 0 ? (
                                      <div className="rounded-md border border-amber-200 bg-amber-50 p-2 text-[10px] text-amber-800">
                                        선택된 메뉴에 사용 가능한 채번 규칙이 없습니다
                                      </div>
                                    ) : (
                                      <Select
                                        value={col.autoFill?.numberingRuleId || ""}
                                        onValueChange={(value) =>
                                          updateColumnProp(col.key, "autoFill", {
                                            ...col.autoFill,
                                            selectedMenuObjid,
                                            numberingRuleId: value,
                                          })
                                        }
                                      >
                                        <SelectTrigger className="h-7 text-xs">
                                          <SelectValue placeholder="채번 규칙 선택" />
                                        </SelectTrigger>
                                        <SelectContent>
                                          {numberingRules.map((rule) => (
                                            <SelectItem key={rule.ruleId} value={rule.ruleId} className="text-xs">
                                              {rule.ruleName}
                                              {rule.description && (
                                                <span className="text-muted-foreground ml-2">- {rule.description}</span>
                                              )}
                                            </SelectItem>
                                          ))}
                                        </SelectContent>
                                      </Select>
                                    )}
                                    {col.autoFill?.numberingRuleId && (
                                      <p className="text-[10px] text-emerald-600">
                                        저장 시 채번 API를 통해 자동 생성됩니다.
                                      </p>
                                    )}
                                  </div>
                                ) : (
                                  <div className="rounded-md border border-amber-200 bg-amber-50 p-2 text-[10px] text-amber-800">
                                    먼저 대상 메뉴를 선택하세요
                                  </div>
                                )}
                              </div>
                            )}

                            {/* 메인 폼에서 복사 설정 */}
                            {col.autoFill?.type === "fromMainForm" && (
                              <div className="space-y-1">
                                <Label className="text-muted-foreground text-[10px]">복사할 필드명</Label>
                                <Input
                                  value={col.autoFill?.sourceField || ""}
                                  onChange={(e) =>
                                    updateColumnProp(col.key, "autoFill", {
                                      ...col.autoFill,
                                      sourceField: e.target.value,
                                    })
                                  }
                                  placeholder="order_no"
                                  className="h-6 text-xs"
                                />
                              </div>
                            )}

                            {/* 고정값 설정 */}
                            {col.autoFill?.type === "fixed" && (
                              <div className="space-y-1">
                                <Label className="text-muted-foreground text-[10px]">고정값</Label>
                                <Input
                                  value={String(col.autoFill?.fixedValue || "")}
                                  onChange={(e) =>
                                    updateColumnProp(col.key, "autoFill", {
                                      ...col.autoFill,
                                      fixedValue: e.target.value,
                                    })
                                  }
                                  placeholder="고정값 입력"
                                  className="h-6 text-xs"
                                />
                              </div>
                            )}

                            {/* 부모채번+순번 설정 */}
                            {col.autoFill?.type === "parentSequence" && (
                              <div className="space-y-2">
                                <div className="space-y-1">
                                  <Label className="text-muted-foreground text-[10px]">부모 번호 필드명</Label>
                                  <Input
                                    value={col.autoFill?.parentField || ""}
                                    onChange={(e) =>
                                      updateColumnProp(col.key, "autoFill", {
                                        ...col.autoFill,
                                        parentField: e.target.value,
                                      })
                                    }
                                    placeholder="work_order_no"
                                    className="h-6 text-xs"
                                  />
                                  <p className="text-muted-foreground/70 text-[10px]">
                                    메인 폼에서 가져올 부모 채번 필드
                                  </p>
                                </div>
                                <div className="flex gap-2">
                                  <div className="flex-1 space-y-1">
                                    <Label className="text-muted-foreground text-[10px]">구분자</Label>
                                    <Input
                                      value={col.autoFill?.separator ?? "-"}
                                      onChange={(e) =>
                                        updateColumnProp(col.key, "autoFill", {
                                          ...col.autoFill,
                                          separator: e.target.value,
                                        })
                                      }
                                      placeholder="-"
                                      className="h-6 text-xs"
                                    />
                                  </div>
                                  <div className="flex-1 space-y-1">
                                    <Label className="text-muted-foreground text-[10px]">순번 자릿수</Label>
                                    <Input
                                      type="number"
                                      min={1}
                                      max={5}
                                      value={col.autoFill?.sequenceLength ?? 2}
                                      onChange={(e) =>
                                        updateColumnProp(col.key, "autoFill", {
                                          ...col.autoFill,
                                          sequenceLength: parseInt(e.target.value) || 2,
                                        })
                                      }
                                      className="h-6 text-xs"
                                    />
                                  </div>
                                </div>
                                <p className="text-[10px] text-emerald-600">
                                  예시: WO-20260223-005{col.autoFill?.separator ?? "-"}
                                  {String(1).padStart(col.autoFill?.sequenceLength ?? 2, "0")}
                                </p>
                              </div>
                            )}
                          </div>
                        )}
                      </div>
                    ))}
                  </div>
                </div>
              </CollapsibleContent>
            </Collapsible>
          )}

          {/* 계산 규칙 - Collapsible (기본 닫힘) */}
          {(isModalMode || isInlineMode) && config.columns.length > 0 && (
            <Collapsible open={calcRulesOpen} onOpenChange={setCalcRulesOpen}>
              <CollapsibleTrigger asChild>
                <button
                  type="button"
                  className="bg-muted/30 hover:bg-muted/50 flex w-full items-center justify-between rounded-lg border px-4 py-2.5 text-left transition-colors"
                >
                  <div className="flex items-center gap-2">
                    <Calculator className="text-muted-foreground h-4 w-4" />
                    <span className="text-sm font-medium">계산 규칙</span>
                    <Badge variant="secondary" className="h-5 text-[10px]">
                      {calculationRules.length}개
                    </Badge>
                  </div>
                  <ChevronDown
                    className={cn(
                      "text-muted-foreground h-4 w-4 transition-transform duration-200",
                      calcRulesOpen && "rotate-180",
                    )}
                  />
                </button>
              </CollapsibleTrigger>
              <CollapsibleContent>
                <div className="space-y-3 rounded-b-lg border border-t-0 p-3">
                  <div className="flex justify-end">
                    <Button
                      type="button"
                      variant="outline"
                      size="sm"
                      onClick={addCalculationRule}
                      className="h-7 px-2 text-xs"
                    >
                      <Plus className="mr-1 h-3 w-3" />
                      추가
                    </Button>
                  </div>

                  <div className="space-y-2">
                    {calculationRules.map((rule) => (
                      <div key={rule.id} className="space-y-1 rounded border p-1.5">
                        <div className="flex items-center gap-1">
                          <Select
                            value={rule.targetColumn}
                            onValueChange={(value) => updateCalculationRule(rule.id, "targetColumn", value)}
                          >
                            <SelectTrigger className="h-6 w-20 text-[10px]">
                              <SelectValue placeholder="결과" />
                            </SelectTrigger>
                            <SelectContent>
                              {config.columns
                                .filter((col) => !col.isSourceDisplay)
                                .map((col) => (
                                  <SelectItem key={col.key} value={col.key} className="text-xs">
                                    {col.title || col.key}
                                  </SelectItem>
                                ))}
                            </SelectContent>
                          </Select>
                          <span className="text-[10px]">=</span>
                          <Input
                            value={rule.formula}
                            onChange={(e) => updateCalculationRule(rule.id, "formula", e.target.value)}
                            placeholder="컬럼 클릭 또는 직접 입력"
                            className="h-6 flex-1 font-mono text-[10px]"
                          />
                          <Button
                            type="button"
                            variant="ghost"
                            size="sm"
                            onClick={() => removeCalculationRule(rule.id)}
                            className="text-destructive h-6 w-6 p-0"
                          >
                            <Trash2 className="h-3 w-3" />
                          </Button>
                        </div>

                        {/* 한글 수식 미리보기 */}
                        {rule.formula && (
                          <p className="bg-muted/50 text-muted-foreground truncate rounded px-1.5 py-0.5 text-[10px]">
                            {config.columns.find((c) => c.key === rule.targetColumn)?.title ||
                              rule.targetColumn ||
                              "결과"}{" "}
                            = {formulaToKorean(rule.formula)}
                          </p>
                        )}

                        {/* 컬럼 칩: 디테일 컬럼 + 소스(품목) 컬럼 + 연산자 */}
                        <div className="flex flex-wrap gap-0.5">
                          {config.columns
                            .filter((col) => col.key !== rule.targetColumn && !col.isSourceDisplay)
                            .map((col) => (
                              <Button
                                key={col.key}
                                type="button"
                                variant="secondary"
                                size="sm"
                                onClick={() => insertColumnToFormula(rule.id, col.key)}
                                className="h-4 px-1 text-[9px]"
                              >
                                {col.title || col.key}
                              </Button>
                            ))}
                          {config.columns
                            .filter((col) => col.isSourceDisplay)
                            .map((col) => (
                              <Button
                                key={col.key}
                                type="button"
                                variant="outline"
                                size="sm"
                                onClick={() => insertColumnToFormula(rule.id, col.key)}
                                className="text-primary h-4 border-dashed px-1 text-[9px]"
                                title="품목 정보 컬럼"
                              >
                                {col.title || col.key}
                              </Button>
                            ))}
                          {["+", "-", "*", "/", "(", ")"].map((op) => (
                            <Button
                              key={op}
                              type="button"
                              variant="outline"
                              size="sm"
                              onClick={() => insertColumnToFormula(rule.id, op)}
                              className="h-4 w-4 p-0 font-mono text-[9px]"
                            >
                              {op}
                            </Button>
                          ))}
                        </div>
                      </div>
                    ))}

                    {calculationRules.length === 0 && (
                      <div className="text-muted-foreground py-4 text-center">
                        <Calculator className="mx-auto mb-2 h-6 w-6 opacity-30" />
                        <p className="text-xs">아직 계산 규칙이 없어요</p>
                        <p className="mt-0.5 text-[10px]">위의 추가 버튼으로 수식을 만들어보세요</p>
                      </div>
                    )}
                  </div>
                </div>
              </CollapsibleContent>
            </Collapsible>
          )}
        </TabsContent>

        {/* Entity 조인 설정 탭 */}
        <TabsContent value="entityJoin" className="mt-4 space-y-4">
          <div className="bg-muted/30 space-y-3 rounded-lg border p-4">
            <div className="flex items-center gap-2">
              <Link2 className="text-primary h-4 w-4" />
              <span className="text-sm font-medium">연결된 테이블 데이터 표시</span>
            </div>
            <p className="text-muted-foreground text-[11px]">
              FK 컬럼을 기반으로 참조 테이블의 데이터를 자동으로 가져와서 표시해요
            </p>

            {loadingEntityJoins ? (
              <div className="text-muted-foreground flex items-center gap-2 text-xs">
                <div className="border-primary h-3 w-3 animate-spin rounded-full border-2 border-t-transparent" />
                조인 가능한 컬럼을 찾고 있어요...
              </div>
            ) : entityJoinData.joinTables.length === 0 ? (
              <div className="rounded-md border-2 border-dashed p-4 text-center">
                <Link2 className="text-muted-foreground mx-auto mb-2 h-8 w-8 opacity-30" />
                <p className="text-muted-foreground text-sm">
                  {entityJoinTargetTable ? "조인 가능한 컬럼이 없어요" : "저장 테이블을 먼저 설정해주세요"}
                </p>
                {entityJoinTargetTable && (
                  <p className="text-muted-foreground mt-0.5 text-xs">
                    테이블 타입 관리에서 엔티티 관계를 설정해보세요
                  </p>
                )}
              </div>
            ) : (
              <div className="space-y-2">
                {entityJoinData.joinTables.map((joinTable, tableIndex) => {
                  const sourceColumn = (joinTable as any).joinConfig?.sourceColumn || "";
                  const activeCount = joinTable.availableColumns.filter((col) =>
                    isEntityJoinColumnActive(joinTable.tableName, sourceColumn, col.columnName),
                  ).length;
                  const isSubOpen = entityJoinSubOpen[tableIndex] ?? false;

                  return (
                    <Collapsible
                      key={tableIndex}
                      open={isSubOpen}
                      onOpenChange={(open) => setEntityJoinSubOpen((prev) => ({ ...prev, [tableIndex]: open }))}
                    >
                      <CollapsibleTrigger asChild>
                        <button
                          type="button"
                          className="border-primary/20 bg-primary/5 hover:bg-primary/10 flex w-full items-center justify-between rounded-md border px-3 py-2 text-left transition-colors"
                        >
                          <div className="flex items-center gap-2">
                            <Link2 className="text-primary h-3 w-3" />
                            <span className="truncate text-xs font-medium">{joinTable.tableName}</span>
                            <Badge variant="secondary" className="h-5 text-[10px]">
                              {activeCount > 0
                                ? `${activeCount}/${joinTable.availableColumns.length}개 선택`
                                : `${joinTable.availableColumns.length}개 컬럼`}
                            </Badge>
                          </div>
                          <ChevronDown
                            className={cn(
                              "text-muted-foreground h-3 w-3 transition-transform duration-200",
                              isSubOpen && "rotate-180",
                            )}
                          />
                        </button>
                      </CollapsibleTrigger>
                      <CollapsibleContent>
                        <div className="border-primary/20 bg-primary/5 space-y-0.5 rounded-b-md border border-t-0 p-2">
                          {joinTable.availableColumns.map((column, colIndex) => {
                            const isActive = isEntityJoinColumnActive(
                              joinTable.tableName,
                              sourceColumn,
                              column.columnName,
                            );
                            const matchingCol = config.columns.find((c) => c.key === column.columnName);
                            const displayField = matchingCol?.key || column.columnName;

                            return (
                              <div
                                key={colIndex}
                                className={cn(
                                  "hover:bg-primary/10 flex cursor-pointer items-center gap-2 rounded px-2 py-1",
                                  isActive && "bg-primary/10",
                                )}
                                onClick={() =>
                                  toggleEntityJoinColumn(
                                    joinTable.tableName,
                                    sourceColumn,
                                    column.columnName,
                                    column.columnLabel,
                                    displayField,
                                  )
                                }
                              >
                                <Checkbox checked={isActive} className="pointer-events-none h-3.5 w-3.5" />
                                <Link2 className="text-primary h-3 w-3 flex-shrink-0" />
                                <span className="truncate text-xs">{column.columnLabel}</span>
                                <span className="text-primary/80 ml-auto text-[10px]">
                                  {column.inputType || column.dataType}
                                </span>
                              </div>
                            );
                          })}
                        </div>
                      </CollapsibleContent>
                    </Collapsible>
                  );
                })}
              </div>
            )}

            {/* 현재 설정된 Entity 조인 목록 - Collapsible */}
            {config.entityJoins && config.entityJoins.length > 0 && (
              <Collapsible open={configuredJoinsOpen} onOpenChange={setConfiguredJoinsOpen}>
                <CollapsibleTrigger asChild>
                  <button
                    type="button"
                    className="bg-muted/30 hover:bg-muted/50 flex w-full items-center justify-between rounded-md border px-3 py-2 text-left transition-colors"
                  >
                    <div className="flex items-center gap-2">
                      <Database className="text-muted-foreground h-3.5 w-3.5" />
                      <span className="text-xs font-medium">설정된 조인</span>
                      <Badge variant="secondary" className="h-5 text-[10px]">
                        {config.entityJoins.length}개
                      </Badge>
                    </div>
                    <ChevronDown
                      className={cn(
                        "text-muted-foreground h-3 w-3 transition-transform duration-200",
                        configuredJoinsOpen && "rotate-180",
                      )}
                    />
                  </button>
                </CollapsibleTrigger>
                <CollapsibleContent>
                  <div className="space-y-1 rounded-b-md border border-t-0 p-2">
                    {config.entityJoins.map((join, idx) => (
                      <div
                        key={idx}
                        className="bg-muted/30 flex items-center gap-1 rounded border px-2 py-1 text-[10px]"
                      >
                        <Database className="text-primary h-3 w-3 flex-shrink-0" />
                        <span className="truncate font-medium">{join.sourceColumn}</span>
                        <ArrowRight className="text-muted-foreground h-3 w-3 flex-shrink-0" />
                        <span className="truncate">{join.referenceTable}</span>
                        <span className="text-muted-foreground truncate">
                          ({join.columns.map((c) => c.referenceField).join(", ")})
                        </span>
                        <Button
                          type="button"
                          variant="ghost"
                          size="sm"
                          onClick={() => {
                            updateConfig({
                              entityJoins: config.entityJoins!.filter((_, i) => i !== idx),
                            });
                          }}
                          className="text-destructive ml-auto h-4 w-4 flex-shrink-0 p-0"
                        >
                          <Trash2 className="h-3 w-3" />
                        </Button>
                      </div>
                    ))}
                  </div>
                </CollapsibleContent>
              </Collapsible>
            )}
          </div>
        </TabsContent>
      </Tabs>
    </div>
  );
};

V2RepeaterConfigPanel.displayName = "V2RepeaterConfigPanel";

export default V2RepeaterConfigPanel;
