"use client";

import React, { useState, useEffect, useMemo, useCallback, useRef } from "react";
import { TableListConfig, ColumnConfig } from "./types";
import { WebType } from "@/types/common";
import { tableTypeApi } from "@/lib/api/screen";
import { entityJoinApi } from "@/lib/api/entityJoin";
import { codeCache } from "@/lib/caching/codeCache";
import { useEntityJoinOptimization } from "@/lib/hooks/useEntityJoinOptimization";
import { Button } from "@/components/ui/button";
import {
  ChevronLeft,
  ChevronRight,
  ChevronsLeft,
  ChevronsRight,
  RefreshCw,
  ArrowUp,
  ArrowDown,
  TableIcon,
  Settings,
  X,
} from "lucide-react";
import { Checkbox } from "@/components/ui/checkbox";
import { cn } from "@/lib/utils";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { AdvancedSearchFilters } from "@/components/screen/filters/AdvancedSearchFilters";
import { SingleTableWithSticky } from "./SingleTableWithSticky";
import { CardModeRenderer } from "./CardModeRenderer";

// ========================================
// 캐시 및 유틸리티
// ========================================

const tableColumnCache = new Map<string, { columns: any[]; timestamp: number }>();
const tableInfoCache = new Map<string, { tables: any[]; timestamp: number }>();
const TABLE_CACHE_TTL = 5 * 60 * 1000; // 5분

const cleanupTableCache = () => {
  const now = Date.now();
  for (const [key, entry] of tableColumnCache.entries()) {
    if (now - entry.timestamp > TABLE_CACHE_TTL) {
      tableColumnCache.delete(key);
    }
  }
  for (const [key, entry] of tableInfoCache.entries()) {
    if (now - entry.timestamp > TABLE_CACHE_TTL) {
      tableInfoCache.delete(key);
    }
  }
};

if (typeof window !== "undefined") {
  setInterval(cleanupTableCache, 10 * 60 * 1000);
}

const debounceTimers = new Map<string, NodeJS.Timeout>();
const activeRequests = new Map<string, Promise<any>>();

const debouncedApiCall = <T extends any[], R>(key: string, fn: (...args: T) => Promise<R>, delay: number = 300) => {
  return (...args: T): Promise<R> => {
    const activeRequest = activeRequests.get(key);
    if (activeRequest) {
      return activeRequest as Promise<R>;
    }

    return new Promise((resolve, reject) => {
      const existingTimer = debounceTimers.get(key);
      if (existingTimer) {
        clearTimeout(existingTimer);
      }

      const timer = setTimeout(async () => {
        try {
          const requestPromise = fn(...args);
          activeRequests.set(key, requestPromise);
          const result = await requestPromise;
          resolve(result);
        } catch (error) {
          reject(error);
        } finally {
          debounceTimers.delete(key);
          activeRequests.delete(key);
        }
      }, delay);

      debounceTimers.set(key, timer);
    });
  };
};

// ========================================
// Props 인터페이스
// ========================================

export interface TableListComponentProps {
  component: any;
  isDesignMode?: boolean;
  isSelected?: boolean;
  isInteractive?: boolean;
  onClick?: () => void;
  onDragStart?: (e: React.DragEvent) => void;
  onDragEnd?: (e: React.DragEvent) => void;
  className?: string;
  style?: React.CSSProperties;
  formData?: Record<string, any>;
  onFormDataChange?: (data: any) => void;
  config?: TableListConfig;
  size?: { width: number; height: number };
  position?: { x: number; y: number; z?: number };
  componentConfig?: any;
  selectedScreen?: any;
  onZoneComponentDrop?: any;
  onZoneClick?: any;
  tableName?: string;
  onRefresh?: () => void;
  onClose?: () => void;
  screenId?: string;
  onSelectedRowsChange?: (selectedRows: any[], selectedRowsData: any[]) => void;
  onConfigChange?: (config: any) => void;
  refreshKey?: number;
}

// ========================================
// 메인 컴포넌트
// ========================================

export const TableListComponent: React.FC<TableListComponentProps> = ({
  component,
  isDesignMode = false,
  isSelected = false,
  onClick,
  onDragStart,
  onDragEnd,
  config,
  className,
  style,
  onFormDataChange,
  componentConfig,
  onSelectedRowsChange,
  onConfigChange,
  refreshKey,
  tableName,
}) => {
  // ========================================
  // 설정 및 스타일
  // ========================================

  const tableConfig = {
    ...config,
    ...component.config,
    ...componentConfig,
  } as TableListConfig;

  // selectedTable 안전하게 추출 (문자열인지 확인)
  let finalSelectedTable =
    componentConfig?.selectedTable || component.config?.selectedTable || config?.selectedTable || tableName;

  console.log("🔍 TableListComponent 초기화:", {
    componentConfigSelectedTable: componentConfig?.selectedTable,
    componentConfigSelectedTableType: typeof componentConfig?.selectedTable,
    componentConfigSelectedTable2: component.config?.selectedTable,
    componentConfigSelectedTable2Type: typeof component.config?.selectedTable,
    configSelectedTable: config?.selectedTable,
    configSelectedTableType: typeof config?.selectedTable,
    screenTableName: tableName,
    screenTableNameType: typeof tableName,
    finalSelectedTable,
    finalSelectedTableType: typeof finalSelectedTable,
  });

  // 객체인 경우 tableName 속성 추출 시도
  if (typeof finalSelectedTable === "object" && finalSelectedTable !== null) {
    console.warn("⚠️ selectedTable이 객체입니다:", finalSelectedTable);
    finalSelectedTable = (finalSelectedTable as any).tableName || (finalSelectedTable as any).name || tableName;
    console.log("✅ 객체에서 추출한 테이블명:", finalSelectedTable);
  }

  tableConfig.selectedTable = finalSelectedTable;

  console.log(
    "✅ 최종 tableConfig.selectedTable:",
    tableConfig.selectedTable,
    "타입:",
    typeof tableConfig.selectedTable,
  );

  const buttonColor = component.style?.labelColor || "#212121";
  const buttonTextColor = component.config?.buttonTextColor || "#ffffff";

  const gridColumns = component.gridColumns || 1;
  let calculatedWidth: string;

  if (isDesignMode) {
    if (gridColumns === 1) {
      calculatedWidth = "400px";
    } else if (gridColumns === 2) {
      calculatedWidth = "800px";
    } else {
      calculatedWidth = "100%";
    }
  } else {
    calculatedWidth = "100%";
  }

  const componentStyle: React.CSSProperties = {
    width: calculatedWidth,
    height: isDesignMode ? "auto" : "100%",
    minHeight: isDesignMode ? "300px" : "100%",
    display: "flex",
    flexDirection: "column",
    backgroundColor: "hsl(var(--background))",
    overflow: "hidden",
    ...style,
  };

  // ========================================
  // 상태 관리
  // ========================================

  const [data, setData] = useState<Record<string, any>[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [currentPage, setCurrentPage] = useState(1);
  const [totalPages, setTotalPages] = useState(0);
  const [totalItems, setTotalItems] = useState(0);
  const [searchTerm, setSearchTerm] = useState("");
  const [sortColumn, setSortColumn] = useState<string | null>(null);
  const [sortDirection, setSortDirection] = useState<"asc" | "desc">("asc");
  const [columnLabels, setColumnLabels] = useState<Record<string, string>>({});
  const [tableLabel, setTableLabel] = useState<string>("");
  const [localPageSize, setLocalPageSize] = useState<number>(tableConfig.pagination?.pageSize || 20);
  const [displayColumns, setDisplayColumns] = useState<ColumnConfig[]>([]);
  const [joinColumnMapping, setJoinColumnMapping] = useState<Record<string, string>>({});
  const [columnMeta, setColumnMeta] = useState<Record<string, { webType?: string; codeCategory?: string }>>({});
  const [searchValues, setSearchValues] = useState<Record<string, any>>({});
  const [selectedRows, setSelectedRows] = useState<Set<string>>(new Set());
  const [isDragging, setIsDragging] = useState(false);
  const [draggedRowIndex, setDraggedRowIndex] = useState<number | null>(null);
  const [isAllSelected, setIsAllSelected] = useState(false);

  // 필터 설정 관련 상태
  const [isFilterSettingOpen, setIsFilterSettingOpen] = useState(false);
  const [visibleFilterColumns, setVisibleFilterColumns] = useState<Set<string>>(new Set());

  const { optimizedConvertCode } = useEntityJoinOptimization(columnMeta, {
    enableBatchLoading: true,
    preloadCommonCodes: true,
    maxBatchSize: 5,
  });

  // ========================================
  // 컬럼 라벨 가져오기
  // ========================================

  const fetchColumnLabels = async () => {
    if (!tableConfig.selectedTable) return;

    try {
      const cacheKey = `columns_${tableConfig.selectedTable}`;
      const cached = tableColumnCache.get(cacheKey);
      if (cached && Date.now() - cached.timestamp < TABLE_CACHE_TTL) {
        const labels: Record<string, string> = {};
        const meta: Record<string, { webType?: string; codeCategory?: string }> = {};

        cached.columns.forEach((col: any) => {
          labels[col.columnName] = col.displayName || col.comment || col.columnName;
          meta[col.columnName] = {
            webType: col.webType,
            codeCategory: col.codeCategory,
          };
        });

        setColumnLabels(labels);
        setColumnMeta(meta);
        return;
      }

      const columns = await tableTypeApi.getColumns(tableConfig.selectedTable);
      
      // 컬럼 입력 타입 정보 가져오기
      const inputTypes = await tableTypeApi.getColumnInputTypes(tableConfig.selectedTable);
      const inputTypeMap: Record<string, string> = {};
      inputTypes.forEach((col: any) => {
        inputTypeMap[col.columnName] = col.inputType;
      });

      tableColumnCache.set(cacheKey, {
        columns,
        inputTypes,
        timestamp: Date.now(),
      });

      const labels: Record<string, string> = {};
      const meta: Record<string, { webType?: string; codeCategory?: string; inputType?: string }> = {};

      columns.forEach((col: any) => {
        labels[col.columnName] = col.displayName || col.comment || col.columnName;
        meta[col.columnName] = {
          webType: col.webType,
          codeCategory: col.codeCategory,
          inputType: inputTypeMap[col.columnName],
        };
      });

      setColumnLabels(labels);
      setColumnMeta(meta);
    } catch (error) {
      console.error("컬럼 라벨 가져오기 실패:", error);
    }
  };

  // ========================================
  // 테이블 라벨 가져오기
  // ========================================

  const fetchTableLabel = async () => {
    if (!tableConfig.selectedTable) return;

    try {
      const cacheKey = `table_info_${tableConfig.selectedTable}`;
      const cached = tableInfoCache.get(cacheKey);
      if (cached && Date.now() - cached.timestamp < TABLE_CACHE_TTL) {
        const tables = cached.tables || [];
        const tableInfo = tables.find((t: any) => t.tableName === tableConfig.selectedTable);
        const label =
          tableInfo?.displayName || (tableInfo as any)?.comment || tableInfo?.description || tableConfig.selectedTable;
        setTableLabel(label);
        return;
      }

      const tables = await tableTypeApi.getTables();

      tableInfoCache.set(cacheKey, {
        tables,
        timestamp: Date.now(),
      });

      const tableInfo = tables.find((t: any) => t.tableName === tableConfig.selectedTable);
      const label =
        tableInfo?.displayName || (tableInfo as any)?.comment || tableInfo?.description || tableConfig.selectedTable;
      setTableLabel(label);
    } catch (error) {
      console.error("테이블 라벨 가져오기 실패:", error);
    }
  };

  // ========================================
  // 데이터 가져오기
  // ========================================

  const fetchTableDataInternal = useCallback(async () => {
    if (!tableConfig.selectedTable || isDesignMode) {
      setData([]);
      setTotalPages(0);
      setTotalItems(0);
      return;
    }

    // 테이블명 확인 로그
    console.log("🔍 fetchTableDataInternal - selectedTable:", tableConfig.selectedTable);
    console.log("🔍 selectedTable 타입:", typeof tableConfig.selectedTable);
    console.log("🔍 전체 tableConfig:", tableConfig);

    setLoading(true);
    setError(null);

    try {
      const page = tableConfig.pagination?.currentPage || currentPage;
      const pageSize = localPageSize;
      const sortBy = sortColumn || undefined;
      const sortOrder = sortDirection;
      const search = searchTerm || undefined;
      const filters = Object.keys(searchValues).length > 0 ? searchValues : undefined;

      const entityJoinColumns = (tableConfig.columns || [])
        .filter((col) => col.additionalJoinInfo)
        .map((col) => ({
          sourceTable: col.additionalJoinInfo!.sourceTable,
          sourceColumn: col.additionalJoinInfo!.sourceColumn,
          joinAlias: col.additionalJoinInfo!.joinAlias,
          referenceTable: col.additionalJoinInfo!.referenceTable,
        }));

      const hasEntityJoins = entityJoinColumns.length > 0;

      let response;
      if (hasEntityJoins) {
        response = await entityJoinApi.getTableDataWithJoins(tableConfig.selectedTable, {
          page,
          size: pageSize,
          sortBy,
          sortOrder,
          search: filters,
          enableEntityJoin: true,
          additionalJoinColumns: entityJoinColumns,
        });
      } else {
        response = await tableTypeApi.getTableData(tableConfig.selectedTable, {
          page,
          size: pageSize,
          sortBy,
          sortOrder,
          search: filters,
        });
      }

      setData(response.data || []);
      setTotalPages(response.totalPages || 0);
      setTotalItems(response.total || 0);
      setError(null);
    } catch (err: any) {
      console.error("데이터 가져오기 실패:", err);
      setData([]);
      setTotalPages(0);
      setTotalItems(0);
      setError(err.message || "데이터를 불러오지 못했습니다.");
    } finally {
      setLoading(false);
    }
  }, [
    tableConfig.selectedTable,
    tableConfig.pagination?.currentPage,
    tableConfig.columns,
    currentPage,
    localPageSize,
    sortColumn,
    sortDirection,
    searchTerm,
    searchValues,
    isDesignMode,
  ]);

  const fetchTableDataDebounced = useCallback(
    (...args: Parameters<typeof fetchTableDataInternal>) => {
      const key = `fetchData_${tableConfig.selectedTable}_${currentPage}_${sortColumn}_${sortDirection}`;
      return debouncedApiCall(key, fetchTableDataInternal, 300)(...args);
    },
    [fetchTableDataInternal, tableConfig.selectedTable, currentPage, sortColumn, sortDirection],
  );

  // ========================================
  // 이벤트 핸들러
  // ========================================

  const handlePageChange = (newPage: number) => {
    if (newPage < 1 || newPage > totalPages) return;
    setCurrentPage(newPage);
    if (tableConfig.pagination) {
      tableConfig.pagination.currentPage = newPage;
    }
    if (onConfigChange) {
      onConfigChange({ ...tableConfig, pagination: { ...tableConfig.pagination, currentPage: newPage } });
    }
  };

  const handleSort = (column: string) => {
    if (sortColumn === column) {
      setSortDirection(sortDirection === "asc" ? "desc" : "asc");
    } else {
      setSortColumn(column);
      setSortDirection("asc");
    }
  };

  const handleSearchValueChange = (columnName: string, value: any) => {
    setSearchValues((prev) => ({ ...prev, [columnName]: value }));
  };

  const handleAdvancedSearch = () => {
    setCurrentPage(1);
    fetchTableDataDebounced();
  };

  const handleClearAdvancedFilters = () => {
    setSearchValues({});
    setCurrentPage(1);
    fetchTableDataDebounced();
  };

  const handleRefresh = () => {
    fetchTableDataDebounced();
  };

  const getRowKey = (row: any, index: number) => {
    return row.id || row.uuid || `row-${index}`;
  };

  const handleRowSelection = (rowKey: string, checked: boolean) => {
    const newSelectedRows = new Set(selectedRows);
    if (checked) {
      newSelectedRows.add(rowKey);
    } else {
      newSelectedRows.delete(rowKey);
    }
    setSelectedRows(newSelectedRows);

    const selectedRowsData = data.filter((row, index) => newSelectedRows.has(getRowKey(row, index)));
    if (onSelectedRowsChange) {
      onSelectedRowsChange(Array.from(newSelectedRows), selectedRowsData);
    }
    if (onFormDataChange) {
      onFormDataChange({ selectedRows: Array.from(newSelectedRows), selectedRowsData });
    }

    const allRowsSelected = data.every((row, index) => newSelectedRows.has(getRowKey(row, index)));
    setIsAllSelected(allRowsSelected && data.length > 0);
  };

  const handleSelectAll = (checked: boolean) => {
    if (checked) {
      const allKeys = data.map((row, index) => getRowKey(row, index));
      const newSelectedRows = new Set(allKeys);
      setSelectedRows(newSelectedRows);
      setIsAllSelected(true);

      if (onSelectedRowsChange) {
        onSelectedRowsChange(Array.from(newSelectedRows), data);
      }
      if (onFormDataChange) {
        onFormDataChange({ selectedRows: Array.from(newSelectedRows), selectedRowsData: data });
      }
    } else {
      setSelectedRows(new Set());
      setIsAllSelected(false);

      if (onSelectedRowsChange) {
        onSelectedRowsChange([], []);
      }
      if (onFormDataChange) {
        onFormDataChange({ selectedRows: [], selectedRowsData: [] });
      }
    }
  };

  const handleRowClick = (row: any) => {
    console.log("행 클릭:", row);
  };

  const handleRowDragStart = (e: React.DragEvent, row: any, index: number) => {
    setIsDragging(true);
    setDraggedRowIndex(index);
    e.dataTransfer.effectAllowed = "move";
    e.dataTransfer.setData("application/json", JSON.stringify(row));
  };

  const handleRowDragEnd = (e: React.DragEvent) => {
    setIsDragging(false);
    setDraggedRowIndex(null);
  };

  const handleClick = (e: React.MouseEvent) => {
    e.stopPropagation();
    onClick?.();
  };

  // ========================================
  // 컬럼 관련
  // ========================================

  const visibleColumns = useMemo(() => {
    let cols = (tableConfig.columns || []).filter((col) => col.visible !== false);

    if (tableConfig.checkbox?.enabled) {
      const checkboxCol: ColumnConfig = {
        columnName: "__checkbox__",
        displayName: "",
        visible: true,
        sortable: false,
        searchable: false,
        width: 50,
        align: "center",
        order: -1,
      };

      if (tableConfig.checkbox.position === "right") {
        cols = [...cols, checkboxCol];
      } else {
        cols = [checkboxCol, ...cols];
      }
    }

    return cols.sort((a, b) => (a.order || 0) - (b.order || 0));
  }, [tableConfig.columns, tableConfig.checkbox]);

  const getColumnWidth = (column: ColumnConfig) => {
    if (column.columnName === "__checkbox__") return 50;
    if (column.width) return column.width;

    switch (column.format) {
      case "date":
        return 120;
      case "number":
      case "currency":
        return 100;
      case "boolean":
        return 80;
      default:
        return 150;
    }
  };

  const renderCheckboxHeader = () => {
    if (!tableConfig.checkbox?.selectAll) return null;

    return <Checkbox checked={isAllSelected} onCheckedChange={handleSelectAll} aria-label="전체 선택" />;
  };

  const renderCheckboxCell = (row: any, index: number) => {
    const rowKey = getRowKey(row, index);
    const isChecked = selectedRows.has(rowKey);

    return (
      <Checkbox
        checked={isChecked}
        onCheckedChange={(checked) => handleRowSelection(rowKey, checked as boolean)}
        aria-label={`행 ${index + 1} 선택`}
      />
    );
  };

  const formatCellValue = useCallback(
    (value: any, column: ColumnConfig, rowData?: Record<string, any>) => {
      if (value === null || value === undefined) return "-";

      // 🎯 엔티티 컬럼 표시 설정이 있는 경우
      if (column.entityDisplayConfig && rowData) {
        // displayColumns 또는 selectedColumns 둘 다 체크
        const displayColumns = column.entityDisplayConfig.displayColumns || column.entityDisplayConfig.selectedColumns;
        const separator = column.entityDisplayConfig.separator;

        if (displayColumns && displayColumns.length > 0) {
          // 선택된 컬럼들의 값을 구분자로 조합
          const values = displayColumns
            .map((colName) => {
              const cellValue = rowData[colName];
              if (cellValue === null || cellValue === undefined) return "";
              return String(cellValue);
            })
            .filter((v) => v !== ""); // 빈 값 제외

          return values.join(separator || " - ");
        }
      }

      const meta = columnMeta[column.columnName];
      if (meta?.webType && meta?.codeCategory) {
        const convertedValue = optimizedConvertCode(value, meta.codeCategory);
        if (convertedValue !== value) return convertedValue;
      }

      // inputType 기반 포맷팅 (columnMeta에서 가져온 inputType 우선)
      const inputType = meta?.inputType || column.inputType;
      if (inputType === "number" || inputType === "decimal") {
        if (value !== null && value !== undefined && value !== "") {
          const numValue = typeof value === "string" ? parseFloat(value) : value;
          if (!isNaN(numValue)) {
            return numValue.toLocaleString("ko-KR");
          }
        }
        return String(value);
      }

      switch (column.format) {
        case "number":
          if (value !== null && value !== undefined && value !== "") {
            const numValue = typeof value === "string" ? parseFloat(value) : value;
            if (!isNaN(numValue)) {
              return numValue.toLocaleString("ko-KR");
            }
          }
          return String(value);
        case "date":
          if (value) {
            try {
              const date = new Date(value);
              return date.toLocaleDateString("ko-KR");
            } catch {
              return value;
            }
          }
          return "-";
        case "number":
          return typeof value === "number" ? value.toLocaleString() : value;
        case "currency":
          return typeof value === "number" ? `₩${value.toLocaleString()}` : value;
        case "boolean":
          return value ? "예" : "아니오";
        default:
          return String(value);
      }
    },
    [columnMeta, optimizedConvertCode],
  );

  // ========================================
  // useEffect 훅
  // ========================================

  // 필터 설정 localStorage 키 생성
  const filterSettingKey = useMemo(() => {
    if (!tableConfig.selectedTable) return null;
    return `tableList_filterSettings_${tableConfig.selectedTable}`;
  }, [tableConfig.selectedTable]);

  // 저장된 필터 설정 불러오기
  useEffect(() => {
    if (!filterSettingKey) return;

    try {
      const saved = localStorage.getItem(filterSettingKey);
      if (saved) {
        const savedFilters = JSON.parse(saved);
        setVisibleFilterColumns(new Set(savedFilters));
      } else {
        // 초기값: 모든 필터 표시
        const allFilters = (tableConfig.filter?.filters || []).map((f) => f.columnName);
        setVisibleFilterColumns(new Set(allFilters));
      }
    } catch (error) {
      console.error("필터 설정 불러오기 실패:", error);
      // 기본값으로 모든 필터 표시
      const allFilters = (tableConfig.filter?.filters || []).map((f) => f.columnName);
      setVisibleFilterColumns(new Set(allFilters));
    }
  }, [filterSettingKey, tableConfig.filter?.filters]);

  // 필터 설정 저장
  const saveFilterSettings = useCallback(() => {
    if (!filterSettingKey) return;

    try {
      localStorage.setItem(filterSettingKey, JSON.stringify(Array.from(visibleFilterColumns)));
      setIsFilterSettingOpen(false);
    } catch (error) {
      console.error("필터 설정 저장 실패:", error);
    }
  }, [filterSettingKey, visibleFilterColumns]);

  // 필터 토글
  const toggleFilterVisibility = useCallback((columnName: string) => {
    setVisibleFilterColumns((prev) => {
      const newSet = new Set(prev);
      if (newSet.has(columnName)) {
        newSet.delete(columnName);
      } else {
        newSet.add(columnName);
      }
      return newSet;
    });
  }, []);

  // 표시할 필터 목록
  const activeFilters = useMemo(() => {
    return (tableConfig.filter?.filters || []).filter((f) => visibleFilterColumns.has(f.columnName));
  }, [tableConfig.filter?.filters, visibleFilterColumns]);

  useEffect(() => {
    fetchColumnLabels();
    fetchTableLabel();
  }, [tableConfig.selectedTable]);

  useEffect(() => {
    if (!isDesignMode && tableConfig.selectedTable) {
      fetchTableDataDebounced();
    }
  }, [
    tableConfig.selectedTable,
    currentPage,
    localPageSize,
    sortColumn,
    sortDirection,
    searchTerm,
    refreshKey,
    isDesignMode,
  ]);

  useEffect(() => {
    if (tableConfig.refreshInterval && !isDesignMode) {
      const interval = setInterval(() => {
        fetchTableDataDebounced();
      }, tableConfig.refreshInterval * 1000);

      return () => clearInterval(interval);
    }
  }, [tableConfig.refreshInterval, isDesignMode]);

  // ========================================
  // 페이지네이션 JSX
  // ========================================

  const paginationJSX = useMemo(() => {
    if (!tableConfig.pagination?.enabled || isDesignMode) return null;

    return (
      <div
        className="w-full h-14 flex items-center justify-center relative border-t-2 border-border bg-background px-4 flex-shrink-0 sm:h-[60px] sm:px-6"
      >
        {/* 중앙 페이지네이션 컨트롤 */}
        <div
          className="flex items-center gap-2 sm:gap-4"
        >
          <Button
            variant="outline"
            size="sm"
            onClick={() => handlePageChange(1)}
            disabled={currentPage === 1 || loading}
            className="h-8 w-8 p-0 sm:h-9 sm:w-auto sm:px-3"
          >
            <ChevronsLeft className="h-3 w-3 sm:h-4 sm:w-4" />
          </Button>
          <Button
            variant="outline"
            size="sm"
            onClick={() => handlePageChange(currentPage - 1)}
            disabled={currentPage === 1 || loading}
            className="h-8 w-8 p-0 sm:h-9 sm:w-auto sm:px-3"
          >
            <ChevronLeft className="h-3 w-3 sm:h-4 sm:w-4" />
          </Button>

          <span className="text-xs font-medium text-foreground min-w-[60px] text-center sm:text-sm sm:min-w-[80px]">
            {currentPage} / {totalPages || 1}
          </span>

          <Button
            variant="outline"
            size="sm"
            onClick={() => handlePageChange(currentPage + 1)}
            disabled={currentPage >= totalPages || loading}
            className="h-8 w-8 p-0 sm:h-9 sm:w-auto sm:px-3"
          >
            <ChevronRight className="h-3 w-3 sm:h-4 sm:w-4" />
          </Button>
          <Button
            variant="outline"
            size="sm"
            onClick={() => handlePageChange(totalPages)}
            disabled={currentPage >= totalPages || loading}
            className="h-8 w-8 p-0 sm:h-9 sm:w-auto sm:px-3"
          >
            <ChevronsRight className="h-3 w-3 sm:h-4 sm:w-4" />
          </Button>

          <span className="text-[10px] text-muted-foreground ml-2 sm:text-xs sm:ml-4">
            전체 {totalItems.toLocaleString()}개
          </span>
        </div>

        {/* 우측 새로고침 버튼 */}
        <Button
          variant="ghost"
          size="sm"
          onClick={handleRefresh}
          disabled={loading}
          className="absolute right-2 h-8 w-8 p-0 sm:right-6 sm:h-9 sm:w-auto sm:px-3"
        >
          <RefreshCw className={cn("h-3 w-3", loading && "animate-spin")} />
        </Button>
      </div>
    );
  }, [tableConfig.pagination, isDesignMode, currentPage, totalPages, totalItems, loading]);

  // ========================================
  // 렌더링
  // ========================================

  const domProps = {
    onClick: handleClick,
    onDragStart: isDesignMode ? onDragStart : undefined,
    onDragEnd: isDesignMode ? onDragEnd : undefined,
    draggable: isDesignMode,
    className: cn(className, isDesignMode && "cursor-move"),
    style: componentStyle,
  };

  // 카드 모드
  if (tableConfig.displayMode === "card" && !isDesignMode) {
    return (
      <div {...domProps}>
        <CardModeRenderer
          data={data}
          loading={loading}
          error={error}
          cardConfig={tableConfig.cardConfig}
          onRowClick={handleRowClick}
        />
        {paginationJSX}
      </div>
    );
  }

  // SingleTableWithSticky 모드
  if (tableConfig.stickyHeader && !isDesignMode) {
    return (
      <div {...domProps}>
        {tableConfig.showHeader && (
          <div className="px-4 py-3 border-b border-border sm:px-6 sm:py-4">
            <h2 className="text-base font-semibold text-foreground sm:text-lg">
              {tableConfig.title || tableLabel || finalSelectedTable}
            </h2>
          </div>
        )}

        {tableConfig.filter?.enabled && (
          <div className="px-4 py-3 border-b border-border sm:px-6 sm:py-4">
            <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:gap-4">
              <div className="flex-1">
                <AdvancedSearchFilters
                  filters={activeFilters}
                  searchValues={searchValues}
                  onSearchValueChange={handleSearchValueChange}
                  onSearch={handleAdvancedSearch}
                  onClear={handleClearAdvancedFilters}
                />
              </div>
              <Button
                variant="outline"
                size="sm"
                onClick={() => setIsFilterSettingOpen(true)}
                className="flex-shrink-0 w-full sm:w-auto sm:mt-1"
              >
                <Settings className="mr-2 h-4 w-4" />
                필터 설정
              </Button>
            </div>
          </div>
        )}

        <div style={{ flex: 1, overflow: "hidden" }}>
          <SingleTableWithSticky
            data={data}
            columns={visibleColumns}
            loading={loading}
            error={error}
            sortColumn={sortColumn}
            sortDirection={sortDirection}
            onSort={handleSort}
            columnLabels={columnLabels}
            renderCheckboxHeader={renderCheckboxHeader}
            renderCheckboxCell={renderCheckboxCell}
            formatCellValue={(value: any, format?: string, columnName?: string, rowData?: Record<string, any>) => {
              const column = visibleColumns.find((c) => c.columnName === columnName);
              return column ? formatCellValue(value, column, rowData) : String(value);
            }}
            getColumnWidth={getColumnWidth}
            containerWidth={calculatedWidth}
          />
        </div>

        {paginationJSX}
      </div>
    );
  }

  // 일반 테이블 모드 (네이티브 HTML 테이블)
  return (
    <>
      <div {...domProps}>
        {/* 헤더 */}
        {tableConfig.showHeader && (
          <div className="px-4 py-3 border-b border-border flex-shrink-0 sm:px-6 sm:py-4">
            <h2 className="text-base font-semibold text-foreground sm:text-lg">
              {tableConfig.title || tableLabel || finalSelectedTable}
            </h2>
          </div>
        )}

        {/* 필터 */}
        {tableConfig.filter?.enabled && (
          <div className="px-4 py-3 border-b border-border flex-shrink-0 sm:px-6 sm:py-4">
            <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:gap-4">
              <div className="flex-1">
                <AdvancedSearchFilters
                  filters={activeFilters}
                  searchValues={searchValues}
                  onSearchValueChange={handleSearchValueChange}
                  onSearch={handleAdvancedSearch}
                  onClear={handleClearAdvancedFilters}
                />
              </div>
              <Button
                variant="outline"
                size="sm"
                onClick={() => setIsFilterSettingOpen(true)}
                className="flex-shrink-0 w-full sm:w-auto sm:mt-1"
              >
                <Settings className="mr-2 h-4 w-4" />
                필터 설정
              </Button>
            </div>
          </div>
        )}

        {/* 테이블 컨테이너 */}
        <div className="flex-1 flex flex-col overflow-hidden w-full max-w-full">
          {/* 스크롤 영역 */}
          <div
            className="w-full max-w-full h-[400px] overflow-y-scroll overflow-x-auto bg-background sm:h-[500px]"
          >
            {/* 테이블 */}
            <table
              className="w-full max-w-full table-mobile-fixed"
              style={{
                borderCollapse: "collapse",
                width: "100%",
              }}
            >
              {/* 헤더 (sticky) */}
              <thead
                className="sticky top-0 z-10 bg-background"
              >
                <tr className="h-10 border-b border-border sm:h-12">
                  {visibleColumns.map((column) => (
                    <th
                      key={column.columnName}
                      className={cn(
                        "h-10 px-2 py-2 text-xs font-semibold text-foreground overflow-hidden text-ellipsis bg-background sm:h-12 sm:px-6 sm:py-3 sm:text-sm sm:whitespace-nowrap",
                        column.sortable && "cursor-pointer"
                      )}
                      style={{
                        textAlign: column.align || "left",
                        width: `${100 / visibleColumns.length}%`, // 컬럼 수에 따라 균등 분배
                      }}
                      onClick={() => column.sortable && handleSort(column.columnName)}
                    >
                      {column.columnName === "__checkbox__" ? (
                        renderCheckboxHeader()
                      ) : (
                        <div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
                          <span>{columnLabels[column.columnName] || column.displayName}</span>
                          {column.sortable && sortColumn === column.columnName && (
                            <span>{sortDirection === "asc" ? "↑" : "↓"}</span>
                          )}
                        </div>
                      )}
                    </th>
                  ))}
                </tr>
              </thead>

              {/* 바디 (스크롤) */}
              <tbody>
                {loading ? (
                  <tr>
                    <td colSpan={visibleColumns.length} className="p-12 text-center">
                      <div className="flex flex-col items-center gap-3">
                        <RefreshCw className="h-8 w-8 animate-spin text-muted-foreground" />
                        <div className="text-sm font-medium text-muted-foreground">로딩 중...</div>
                      </div>
                    </td>
                  </tr>
                ) : error ? (
                  <tr>
                    <td colSpan={visibleColumns.length} className="p-12 text-center">
                      <div className="flex flex-col items-center gap-3">
                        <div className="text-sm font-medium text-destructive">오류 발생</div>
                        <div className="text-xs text-muted-foreground">{error}</div>
                      </div>
                    </td>
                  </tr>
                ) : data.length === 0 ? (
                  <tr>
                    <td colSpan={visibleColumns.length} className="p-12 text-center">
                      <div className="flex flex-col items-center gap-3">
                        <TableIcon className="h-12 w-12 text-muted-foreground/50" />
                        <div className="text-sm font-medium text-muted-foreground">데이터가 없습니다</div>
                        <div className="text-xs text-muted-foreground">
                          조건을 변경하거나 새로운 데이터를 추가해보세요
                        </div>
                      </div>
                    </td>
                  </tr>
                ) : (
                  data.map((row, index) => (
                    <tr
                      key={index}
                      draggable={!isDesignMode}
                      onDragStart={(e) => handleRowDragStart(e, row, index)}
                      onDragEnd={handleRowDragEnd}
                      className={cn(
                        "h-14 border-b transition-colors bg-background hover:bg-muted/50 cursor-pointer sm:h-16"
                      )}
                      onClick={() => handleRowClick(row)}
                    >
                      {visibleColumns.map((column) => {
                        const mappedColumnName = joinColumnMapping[column.columnName] || column.columnName;
                        const cellValue = row[mappedColumnName];

                        return (
                          <td
                            key={column.columnName}
                            className={cn(
                              "h-14 px-2 py-2 text-xs text-foreground overflow-hidden text-ellipsis sm:h-16 sm:px-6 sm:py-3 sm:text-sm sm:whitespace-nowrap"
                            )}
                            style={{
                              textAlign: column.align || "left",
                              width: `${100 / visibleColumns.length}%`, // 컬럼 수에 따라 균등 분배
                            }}
                          >
                            {column.columnName === "__checkbox__"
                              ? renderCheckboxCell(row, index)
                              : formatCellValue(cellValue, column, row)}
                          </td>
                        );
                      })}
                    </tr>
                  ))
                )}
              </tbody>
            </table>
          </div>
        </div>

        {/* 페이지네이션 */}
        {paginationJSX}
      </div>

      {/* 필터 설정 다이얼로그 */}
      <Dialog open={isFilterSettingOpen} onOpenChange={setIsFilterSettingOpen}>
        <DialogContent className="max-w-[95vw] sm:max-w-[500px]">
          <DialogHeader>
            <DialogTitle className="text-base sm:text-lg">검색 필터 설정</DialogTitle>
            <DialogDescription className="text-xs sm:text-sm">
              표시할 검색 필터를 선택하세요. 선택하지 않은 필터는 숨겨집니다.
            </DialogDescription>
          </DialogHeader>

          <div className="max-h-[60vh] space-y-3 overflow-y-auto sm:space-y-4">
            {(tableConfig.filter?.filters || []).map((filter) => (
            <div className="flex items-center gap-3 rounded p-2 hover:bg-muted">
                <Checkbox
                  id={`filter-${filter.columnName}`}
                  checked={visibleFilterColumns.has(filter.columnName)}
                  onCheckedChange={() => toggleFilterVisibility(filter.columnName)}
                />
                <Label
                  htmlFor={`filter-${filter.columnName}`}
                  className="flex-1 cursor-pointer text-xs font-normal sm:text-sm"
                >
                  {columnLabels[filter.columnName] || filter.label || filter.columnName}
                </Label>
              </div>
            ))}
          </div>

          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              variant="outline"
              onClick={() => setIsFilterSettingOpen(false)}
              className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
            >
              취소
            </Button>
            <Button onClick={saveFilterSettings} className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm">
              저장
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
};

export const TableListWrapper: React.FC<TableListComponentProps> = (props) => {
  return <TableListComponent {...props} />;
};
