"use client";

import React, { useState, useEffect, useRef, useMemo } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Settings, X, ChevronsUpDown } from "lucide-react";
import { useTableOptions } from "@/contexts/TableOptionsContext";
import { useTableSearchWidgetHeight } from "@/contexts/TableSearchWidgetHeightContext";
import { useActiveTab } from "@/contexts/ActiveTabContext";
import { TableSettingsModal } from "@/components/screen/table-options/TableSettingsModal";
import { TableFilter } from "@/types/table-options";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { ModernDatePicker } from "@/components/screen/filters/ModernDatePicker";
import { useScreenPreview } from "@/contexts/ScreenPreviewContext";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Checkbox } from "@/components/ui/checkbox";
import { cn } from "@/lib/utils";

interface PresetFilter {
  id: string;
  columnName: string;
  columnLabel: string;
  filterType: "text" | "number" | "date" | "select";
  width?: number;
  multiSelect?: boolean; // 다중선택 여부 (select 타입에서만 사용)
}

interface TableSearchWidgetProps {
  component: {
    id: string;
    title?: string;
    style?: {
      width?: string;
      height?: string;
      padding?: string;
      backgroundColor?: string;
    };
    componentConfig?: {
      autoSelectFirstTable?: boolean; // 첫 번째 테이블 자동 선택 여부
      showTableSelector?: boolean; // 테이블 선택 드롭다운 표시 여부
      filterMode?: "dynamic" | "preset"; // 필터 모드
      presetFilters?: PresetFilter[]; // 고정 필터 목록
      targetPanelPosition?: "left" | "right" | "auto"; // 분할 패널에서 대상 패널 위치 (기본: "left")
    };
  };
  screenId?: number; // 화면 ID
  onHeightChange?: (height: number) => void; // 높이 변화 콜백
}

export function TableSearchWidget({ component, screenId, onHeightChange }: TableSearchWidgetProps) {
  const tableOptionsContext = useTableOptions();
  const { registeredTables, selectedTableId, setSelectedTableId, getTable, getActiveTabTables } = tableOptionsContext;
  const { isPreviewMode } = useScreenPreview(); // 미리보기 모드 확인
  const { getAllActiveTabIds, activeTabs } = useActiveTab(); // 활성 탭 정보

  // 높이 관리 context (실제 화면에서만 사용)
  let setWidgetHeight:
    | ((screenId: number, componentId: string, height: number, originalHeight: number) => void)
    | undefined;
  try {
    const heightContext = useTableSearchWidgetHeight();
    setWidgetHeight = heightContext.setWidgetHeight;
  } catch (e) {
    // Context가 없으면 (디자이너 모드) 무시
    setWidgetHeight = undefined;
  }

  // 탭별 필터 값 저장 (탭 ID -> 필터 값)
  const [tabFilterValues, setTabFilterValues] = useState<Record<string, Record<string, any>>>({});

  const [settingsOpen, setSettingsOpen] = useState(false);

  // 활성화된 필터 목록
  const [activeFilters, setActiveFilters] = useState<TableFilter[]>([]);
  const [filterValues, setFilterValues] = useState<Record<string, any>>({});
  // select 타입 필터의 옵션들
  const [selectOptions, setSelectOptions] = useState<Record<string, Array<{ label: string; value: string }>>>({});
  // 선택된 값의 라벨 저장 (데이터 없을 때도 라벨 유지)
  const [selectedLabels, setSelectedLabels] = useState<Record<string, string>>({});

  // 높이 감지를 위한 ref
  const containerRef = useRef<HTMLDivElement>(null);

  const autoSelectFirstTable = component.componentConfig?.autoSelectFirstTable ?? true;
  const showTableSelector = component.componentConfig?.showTableSelector ?? true;
  const filterMode = component.componentConfig?.filterMode ?? "dynamic";
  const presetFilters = component.componentConfig?.presetFilters ?? [];
  const targetPanelPosition = component.componentConfig?.targetPanelPosition ?? "left"; // 기본값: 좌측 패널

  // Map을 배열로 변환
  const allTableList = Array.from(registeredTables.values());

  // 현재 활성 탭 ID 목록
  const activeTabIds = useMemo(() => getAllActiveTabIds(), [activeTabs]);

  // 대상 패널 위치 + 활성 탭에 따라 테이블 필터링
  const tableList = useMemo(() => {
    // 1단계: 활성 탭 기반 필터링
    // - 활성 탭에 속한 테이블만 표시
    // - 탭에 속하지 않은 테이블(parentTabId가 없는)도 포함
    let filteredByTab = allTableList.filter((table) => {
      // 탭에 속하지 않는 테이블은 항상 표시
      if (!table.parentTabId) return true;
      // 활성 탭에 속한 테이블만 표시
      return activeTabIds.includes(table.parentTabId);
    });

    // 2단계: 대상 패널 위치에 따라 추가 필터링
    if (targetPanelPosition !== "auto") {
      filteredByTab = filteredByTab.filter((table) => {
        const tableId = table.tableId.toLowerCase();

        if (targetPanelPosition === "left") {
          // 좌측 패널 대상: card-display만
          return tableId.includes("card-display") || tableId.includes("card");
        } else if (targetPanelPosition === "right") {
          // 우측 패널 대상: datatable, table-list 등 (card-display 제외)
          const isCardDisplay = tableId.includes("card-display") || tableId.includes("card");
          return !isCardDisplay;
        }

        return true;
      });
    }

    // 필터링된 결과가 없으면 탭 기반 필터링 결과만 반환
    if (filteredByTab.length === 0) {
      return allTableList.filter((table) => !table.parentTabId || activeTabIds.includes(table.parentTabId));
    }

    return filteredByTab;
  }, [allTableList, targetPanelPosition, activeTabIds]);

  // currentTable은 tableList(필터링된 목록)에서 가져와야 함
  const currentTable = useMemo(() => {
    if (!selectedTableId) return undefined;

    // 먼저 tableList(필터링된 목록)에서 찾기
    const tableFromList = tableList.find((t) => t.tableId === selectedTableId);
    if (tableFromList) {
      return tableFromList;
    }

    // tableList에 없으면 전체에서 찾기 (폴백)
    const tableFromAll = getTable(selectedTableId);
    return tableFromAll;
  }, [selectedTableId, tableList, getTable]);

  // 🆕 활성 탭 ID 문자열 (변경 감지용)
  const activeTabIdsStr = useMemo(() => activeTabIds.join(","), [activeTabIds]);

  // 🆕 이전 활성 탭 ID 추적 (탭 전환 감지용)
  const prevActiveTabIdsRef = useRef<string>(activeTabIdsStr);

  // 대상 패널의 첫 번째 테이블 자동 선택
  useEffect(() => {
    if (!autoSelectFirstTable) {
      return;
    }

    // 탭 전환 감지: 활성 탭이 변경되었는지 확인
    const tabChanged = prevActiveTabIdsRef.current !== activeTabIdsStr;
    if (tabChanged) {
      // 탭이 변경되면 항상 ref를 갱신 (tableList가 비어 있어도)
      // 이렇게 해야 비동기로 tableList가 나중에 채워질 때 중복 감지하지 않음
      prevActiveTabIdsRef.current = activeTabIdsStr;

      if (tableList.length === 0) {
        // 테이블이 아직 등록되지 않은 상태 (비동기 로드 중)
        // tableList가 나중에 채워지면 아래 폴백 로직에서 처리됨
        return;
      }

      // 탭 전환 시: 해당 탭에 속한 테이블 중 첫 번째 강제 선택
      const activeTabTable = tableList.find((t) => t.parentTabId && activeTabIds.includes(t.parentTabId));
      const targetTable = activeTabTable || tableList[0];

      if (targetTable) {
        setSelectedTableId(targetTable.tableId);
      }
      return; // 탭 전환 시에는 여기서 종료
    }

    // tableList가 비어있으면 아래 로직 스킵
    if (tableList.length === 0) {
      return;
    }

    // 현재 선택된 테이블이 활성 탭에 속하는지 확인
    const isCurrentTableInActiveTab = selectedTableId && tableList.some((t) => {
      if (t.tableId !== selectedTableId) return false;
      // parentTabId가 있는 테이블이면 활성 탭에 속하는지 확인
      if (t.parentTabId) return activeTabIds.includes(t.parentTabId);
      return true; // parentTabId 없는 전역 테이블은 항상 유효
    });

    // 현재 선택된 테이블이 활성 탭에 없거나 미선택이면 첫 번째 테이블 선택
    if (!selectedTableId || !isCurrentTableInActiveTab) {
      const activeTabTable = tableList.find((t) => t.parentTabId && activeTabIds.includes(t.parentTabId));
      const targetTable = activeTabTable || tableList[0];

      if (targetTable && targetTable.tableId !== selectedTableId) {
        setSelectedTableId(targetTable.tableId);
      }
    }
  }, [
    tableList,
    selectedTableId,
    autoSelectFirstTable,
    setSelectedTableId,
    targetPanelPosition,
    activeTabIdsStr,
    activeTabIds,
  ]);

  // 현재 선택된 테이블의 탭 ID (탭별 필터 저장용)
  const currentTableTabId = currentTable?.parentTabId;

  // 탭별 필터 값 저장 키 생성
  const getTabFilterStorageKey = (tableName: string, tabId?: string) => {
    const baseKey = screenId
      ? `table_filter_values_${tableName}_screen_${screenId}`
      : `table_filter_values_${tableName}`;
    return tabId ? `${baseKey}_tab_${tabId}` : baseKey;
  };

  // 탭 변경 시 이전 탭의 필터 값 저장 + 새 탭의 필터 값 복원
  useEffect(() => {
    if (!currentTable?.tableName) return;

    // 현재 필터 값이 있으면 탭별로 저장
    if (Object.keys(filterValues).length > 0 && currentTableTabId) {
      const storageKey = getTabFilterStorageKey(currentTable.tableName, currentTableTabId);
      localStorage.setItem(storageKey, JSON.stringify(filterValues));

      // 메모리 캐시에도 저장
      setTabFilterValues((prev) => ({
        ...prev,
        [currentTableTabId]: filterValues,
      }));
    }
  }, [currentTableTabId, currentTable?.tableName]);

  // 탭 전환 플래그 (탭 복귀 시 필터 재적용을 위해)
  const needsFilterReapplyRef = useRef(false);
  const prevActiveTabIdsForReapplyRef = useRef<string>(activeTabIdsStr);

  // 탭 전환 감지: 플래그만 설정 (실제 적용은 currentTable이 준비된 후)
  useEffect(() => {
    if (prevActiveTabIdsForReapplyRef.current !== activeTabIdsStr) {
      prevActiveTabIdsForReapplyRef.current = activeTabIdsStr;
      needsFilterReapplyRef.current = true;
    }
  }, [activeTabIdsStr]);

  // 탭 복귀 시 기존 필터값 재적용
  // currentTable이 준비되고 필터값이 있을 때 실행
  useEffect(() => {
    if (!needsFilterReapplyRef.current) return;
    if (!currentTable?.onFilterChange) return;

    // 플래그 즉시 해제 (중복 실행 방지)
    needsFilterReapplyRef.current = false;

    // activeFilters와 filterValues가 있으면 직접 onFilterChange 호출
    // applyFilters 클로저 의존성을 피하고 직접 계산
    if (activeFilters.length === 0) return;

    const hasValues = Object.values(filterValues).some(
      (v) => v !== "" && v !== undefined && v !== null,
    );
    if (!hasValues) return;

    const filtersWithValues = activeFilters
      .map((filter) => {
        let filterValue = filterValues[filter.columnName];

        // 날짜 범위 객체 처리
        if (
          filter.filterType === "date" &&
          filterValue &&
          typeof filterValue === "object" &&
          (filterValue.from || filterValue.to)
        ) {
          const formatDate = (date: Date) => {
            const year = date.getFullYear();
            const month = String(date.getMonth() + 1).padStart(2, "0");
            const day = String(date.getDate()).padStart(2, "0");
            return `${year}-${month}-${day}`;
          };
          const fromStr = filterValue.from ? formatDate(filterValue.from) : "";
          const toStr = filterValue.to ? formatDate(filterValue.to) : "";
          if (fromStr && toStr) filterValue = `${fromStr}|${toStr}`;
          else if (fromStr) filterValue = `${fromStr}|`;
          else if (toStr) filterValue = `|${toStr}`;
          else filterValue = "";
        }

        // 배열 처리
        if (Array.isArray(filterValue)) {
          filterValue = filterValue.join("|");
        }

        let operator = "contains";
        if (filter.filterType === "select") operator = "equals";
        else if (filter.filterType === "number") operator = "equals";

        return {
          ...filter,
          value: filterValue || "",
          operator,
        };
      })
      .filter((f) => {
        if (!f.value) return false;
        if (typeof f.value === "string" && f.value === "") return false;
        return true;
      });

    // 직접 onFilterChange 호출 (applyFilters 클로저 우회)
    currentTable.onFilterChange(filtersWithValues);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [currentTable?.onFilterChange, currentTable?.tableName, activeFilters, filterValues]);

  // 필터 적용을 다음 렌더 사이클로 지연 (activeFilters 업데이트 후 적용 보장)
  const pendingFilterApplyRef = useRef<{ values: Record<string, any>; tableName: string } | null>(null);

  useEffect(() => {
    if (pendingFilterApplyRef.current) {
      const { values, tableName } = pendingFilterApplyRef.current;
      // 현재 테이블이 요청된 테이블과 일치하는지 확인 (탭이 빠르게 전환된 경우 방지)
      if (currentTable?.tableName === tableName) {
        applyFilters(values);
      }
      pendingFilterApplyRef.current = null;
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [activeFilters, currentTable?.tableName]);

  // 현재 테이블의 저장된 필터 불러오기 (동적 모드) 또는 고정 필터 적용 (고정 모드)
  useEffect(() => {
    if (!currentTable?.tableName) return;

    // 고정 모드: presetFilters를 activeFilters로 설정
    if (filterMode === "preset") {
      const activeFiltersList: TableFilter[] = presetFilters.map((f) => ({
        columnName: f.columnName,
        operator: "contains",
        value: "",
        filterType: f.filterType,
        width: f.width || 200,
      }));
      setActiveFilters(activeFiltersList);

      // 탭별 저장된 필터 값 복원
      if (currentTableTabId) {
        const storageKey = getTabFilterStorageKey(currentTable.tableName, currentTableTabId);
        const savedValues = localStorage.getItem(storageKey);
        if (savedValues) {
          try {
            const parsedValues = JSON.parse(savedValues);
            setFilterValues(parsedValues);
            // 다음 렌더 사이클에서 필터 적용 (activeFilters 업데이트 후)
            pendingFilterApplyRef.current = { values: parsedValues, tableName: currentTable.tableName };
          } catch {
            setFilterValues({});
          }
        } else {
          setFilterValues({});
        }
      }
      return;
    }

    // 동적 모드: 화면별로 독립적인 필터 설정 불러오기
    // 참고: FilterPanel.tsx에서도 screenId만 사용하여 저장하므로 키가 일치해야 함
    const filterConfigKey = screenId
      ? `table_filters_${currentTable.tableName}_screen_${screenId}`
      : `table_filters_${currentTable.tableName}`;
    const savedFilters = localStorage.getItem(filterConfigKey);

    if (savedFilters) {
      try {
        const parsed = JSON.parse(savedFilters) as Array<{
          columnName: string;
          columnLabel: string;
          inputType: string;
          enabled: boolean;
          filterType: "text" | "number" | "date" | "select";
          width?: number;
        }>;

        // enabled된 필터들만 activeFilters로 설정
        const activeFiltersList: TableFilter[] = parsed
          .filter((f) => f.enabled)
          .map((f) => ({
            columnName: f.columnName,
            operator: "contains",
            value: "",
            filterType: f.filterType,
            width: f.width || 200,
          }));

        setActiveFilters(activeFiltersList);

        // 탭별 저장된 필터 값 복원
        if (currentTableTabId) {
          const valuesStorageKey = getTabFilterStorageKey(currentTable.tableName, currentTableTabId);
          const savedValues = localStorage.getItem(valuesStorageKey);
          if (savedValues) {
            try {
              const parsedValues = JSON.parse(savedValues);
              setFilterValues(parsedValues);
              // 다음 렌더 사이클에서 필터 적용 (activeFilters 업데이트 후)
              pendingFilterApplyRef.current = { values: parsedValues, tableName: currentTable.tableName };
            } catch {
              setFilterValues({});
            }
          } else {
            setFilterValues({});
          }
        } else {
          setFilterValues({});
        }
      } catch (error) {
        console.error("저장된 필터 불러오기 실패:", error);
        // 파싱 에러 시 필터 초기화
        setActiveFilters([]);
        setFilterValues({});
      }
    } else {
      // 필터 설정이 없으면 activeFilters와 filterValues 모두 초기화
      setActiveFilters([]);
      setFilterValues({});
      setSelectOptions({});
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [currentTable?.tableName, filterMode, screenId, currentTableTabId, JSON.stringify(presetFilters)]);

  // select 옵션 로드 (getColumnUniqueValues 변경 시 재로드 - columnMeta 갱신 반영)
  useEffect(() => {
    if (!currentTable?.getColumnUniqueValues || activeFilters.length === 0) {
      return;
    }

    let cancelled = false;

    const loadSelectOptions = async () => {
      const selectFilters = activeFilters.filter((f) => f.filterType === "select");

      if (selectFilters.length === 0) {
        return;
      }

      const loadedOptions: Record<string, Array<{ label: string; value: string }>> = {};
      let hasNewOptions = false;

      for (const filter of selectFilters) {
        try {
          const options = await currentTable.getColumnUniqueValues(filter.columnName);
          if (options && options.length > 0) {
            loadedOptions[filter.columnName] = options;
            hasNewOptions = true;
          }
        } catch (error) {
          console.error("❌ [TableSearchWidget] select 옵션 로드 실패:", filter.columnName, error);
        }
      }

      if (!cancelled && hasNewOptions) {
        setSelectOptions((prev) => {
          // 새로 로드된 옵션으로 항상 갱신 (카테고리 label 정보가 나중에 로드될 수 있으므로)
          // 로드 실패한 컬럼의 기존 옵션은 유지
          return { ...prev, ...loadedOptions };
        });
      }
    };

    loadSelectOptions();

    return () => { cancelled = true; };
  }, [activeFilters, currentTable?.tableName, currentTable?.getColumnUniqueValues, currentTable?.dataCount]);

  // 높이 변화 감지 및 알림 (실제 화면에서만)
  useEffect(() => {
    if (!containerRef.current || !screenId || !setWidgetHeight) return;

    // 컴포넌트의 원래 높이 (디자이너에서 설정한 높이)
    const originalHeight = (component as any).size?.height || 50;

    const resizeObserver = new ResizeObserver((entries) => {
      for (const entry of entries) {
        const newHeight = entry.contentRect.height;

        // Context에 높이 저장 (다른 컴포넌트 위치 조정에 사용)
        setWidgetHeight(screenId, component.id, newHeight, originalHeight);

        // localStorage에 높이 저장 (새로고침 시 복원용)
        localStorage.setItem(
          `table_search_widget_height_screen_${screenId}_${component.id}`,
          JSON.stringify({ height: newHeight, originalHeight }),
        );

        // 콜백이 있으면 호출
        if (onHeightChange) {
          onHeightChange(newHeight);
        }
      }
    });

    resizeObserver.observe(containerRef.current);

    return () => {
      resizeObserver.disconnect();
    };
  }, [screenId, component.id, setWidgetHeight, onHeightChange]);

  // 화면 로딩 시 저장된 높이 복원
  useEffect(() => {
    if (!screenId || !setWidgetHeight) return;

    const storageKey = `table_search_widget_height_screen_${screenId}_${component.id}`;
    const savedData = localStorage.getItem(storageKey);

    if (savedData) {
      try {
        const { height, originalHeight } = JSON.parse(savedData);
        setWidgetHeight(screenId, component.id, height, originalHeight);
      } catch (error) {
        console.error("저장된 높이 복원 실패:", error);
      }
    }
  }, [screenId, component.id, setWidgetHeight]);

  const hasMultipleTables = tableList.length > 1;

  // 필터 값 변경 핸들러
  const handleFilterChange = (columnName: string, value: any) => {
    const newValues = {
      ...filterValues,
      [columnName]: value,
    };

    setFilterValues(newValues);

    // 탭별 필터 값 저장
    if (currentTable?.tableName && currentTableTabId) {
      const storageKey = getTabFilterStorageKey(currentTable.tableName, currentTableTabId);
      localStorage.setItem(storageKey, JSON.stringify(newValues));
    }

    // 실시간 검색: 값 변경 시 즉시 필터 적용
    applyFilters(newValues);
  };

  // 필터 적용 함수
  const applyFilters = (values: Record<string, any> = filterValues) => {
    // 빈 값이 아닌 필터만 적용
    const filtersWithValues = activeFilters
      .map((filter) => {
        let filterValue = values[filter.columnName];

        // 날짜 범위 객체를 처리
        if (
          filter.filterType === "date" &&
          filterValue &&
          typeof filterValue === "object" &&
          (filterValue.from || filterValue.to)
        ) {
          // 날짜 범위 객체를 문자열 형식으로 변환 (백엔드 재시작 불필요)
          const formatDate = (date: Date) => {
            const year = date.getFullYear();
            const month = String(date.getMonth() + 1).padStart(2, "0");
            const day = String(date.getDate()).padStart(2, "0");
            return `${year}-${month}-${day}`;
          };

          // "YYYY-MM-DD|YYYY-MM-DD" 형식으로 변환
          const fromStr = filterValue.from ? formatDate(filterValue.from) : "";
          const toStr = filterValue.to ? formatDate(filterValue.to) : "";

          if (fromStr && toStr) {
            // 둘 다 있으면 파이프로 연결
            filterValue = `${fromStr}|${toStr}`;
          } else if (fromStr) {
            // 시작일만 있으면
            filterValue = `${fromStr}|`;
          } else if (toStr) {
            // 종료일만 있으면
            filterValue = `|${toStr}`;
          } else {
            filterValue = "";
          }
        }

        // 다중선택 배열을 처리 (파이프로 연결된 문자열로 변환)
        // filterType에 관계없이 배열이면 파이프로 연결
        if (Array.isArray(filterValue)) {
          filterValue = filterValue.join("|");
        }

        // 🔧 filterType에 따라 operator 설정
        // - "select" 유형: 정확히 일치 (equals)
        // - "text" 유형: 부분 일치 (contains)
        // - "date", "number": 각각 적절한 처리
        let operator = "contains"; // 기본값
        if (filter.filterType === "select") {
          operator = "equals"; // 선택 필터는 정확히 일치
        } else if (filter.filterType === "number") {
          operator = "equals"; // 숫자도 정확히 일치
        }

        return {
          ...filter,
          value: filterValue || "",
          operator, // operator 추가
        };
      })
      .filter((f) => {
        // 빈 값 체크
        if (!f.value) return false;
        if (typeof f.value === "string" && f.value === "") return false;
        return true;
      });

    if (currentTable?.onFilterChange) {
      currentTable.onFilterChange(filtersWithValues);
    }
  };

  // 필터 초기화
  const handleResetFilters = () => {
    setFilterValues({});
    setSelectedLabels({});
    currentTable?.onFilterChange([]);

    // 탭별 저장된 필터 값도 초기화
    if (currentTable?.tableName && currentTableTabId) {
      const storageKey = getTabFilterStorageKey(currentTable.tableName, currentTableTabId);
      localStorage.removeItem(storageKey);
    }
  };

  // 필터 입력 필드 렌더링
  const renderFilterInput = (filter: TableFilter) => {
    const column = currentTable?.columns.find((c) => c.columnName === filter.columnName);
    const value = filterValues[filter.columnName] || "";
    const width = filter.width || 200; // 기본 너비 200px

    switch (filter.filterType) {
      case "date":
        return (
          <div style={{ width: `${width}px` }}>
            <ModernDatePicker
              label={column?.columnLabel || filter.columnName}
              value={value ? (typeof value === "string" ? { from: new Date(value), to: new Date(value) } : value) : {}}
              onChange={(dateRange) => {
                if (dateRange.from && dateRange.to) {
                  // 기간이 선택되면 from과 to를 모두 저장
                  handleFilterChange(filter.columnName, dateRange);
                } else {
                  handleFilterChange(filter.columnName, "");
                }
              }}
              includeTime={false}
            />
          </div>
        );

      case "number":
        return (
          <Input
            type="number"
            value={value}
            onChange={(e) => handleFilterChange(filter.columnName, e.target.value)}
            className="h-9 text-xs focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:outline-none sm:text-sm"
            style={{ width: `${width}px`, height: "36px", minHeight: "36px", outline: "none", boxShadow: "none" }}
            placeholder={column?.columnLabel}
          />
        );

      case "select": {
        const options = selectOptions[filter.columnName] || [];

        // 중복 제거 (value 기준)
        const uniqueOptions = options.reduce(
          (acc, option) => {
            if (!acc.find((opt) => opt.value === option.value)) {
              acc.push(option);
            }
            return acc;
          },
          [] as Array<{ value: string; label: string }>,
        );

        // 항상 다중선택 모드
        const selectedValues: string[] = Array.isArray(value) ? value : value ? [value] : [];

        // 선택된 값들의 라벨 표시
        const getDisplayText = () => {
          if (selectedValues.length === 0) return column?.columnLabel || "선택";
          if (selectedValues.length === 1) {
            const opt = uniqueOptions.find((o) => o.value === selectedValues[0]);
            return opt?.label || selectedValues[0];
          }
          return `${selectedValues.length}개 선택됨`;
        };

        const handleMultiSelectChange = (optionValue: string, checked: boolean) => {
          let newValues: string[];
          if (checked) {
            newValues = [...selectedValues, optionValue];
          } else {
            newValues = selectedValues.filter((v) => v !== optionValue);
          }
          handleFilterChange(filter.columnName, newValues.length > 0 ? newValues : "");
        };

        return (
          <Popover>
            <PopoverTrigger asChild>
              <Button
                variant="outline"
                role="combobox"
                className={cn(
                  "h-9 min-h-9 justify-between text-xs font-normal focus:ring-0 focus:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 sm:text-sm",
                  selectedValues.length === 0 && "text-muted-foreground",
                )}
                style={{ width: `${width}px`, height: "36px", minHeight: "36px", outline: "none", boxShadow: "none" }}
              >
                <span className="truncate">{getDisplayText()}</span>
                <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
              </Button>
            </PopoverTrigger>
            <PopoverContent className="w-auto p-0" style={{ width: "var(--radix-popover-trigger-width)" }} align="start">
              <div className="max-h-60 overflow-auto">
                {uniqueOptions.length === 0 ? (
                  <div className="text-muted-foreground px-3 py-2 text-xs">옵션 없음</div>
                ) : (
                  <div className="p-1">
                    {uniqueOptions.map((option, index) => (
                      <div
                        key={`${filter.columnName}-multi-${option.value}-${index}`}
                        className="hover:bg-accent flex cursor-pointer items-center space-x-2 rounded-sm px-2 py-1.5"
                        onClick={() => handleMultiSelectChange(option.value, !selectedValues.includes(option.value))}
                      >
                        <Checkbox
                          checked={selectedValues.includes(option.value)}
                          onCheckedChange={(checked) => handleMultiSelectChange(option.value, checked as boolean)}
                          onClick={(e) => e.stopPropagation()}
                        />
                        <span className="truncate text-xs sm:text-sm">{option.label}</span>
                      </div>
                    ))}
                  </div>
                )}
              </div>
              {selectedValues.length > 0 && (
                <div className="border-t p-1">
                  <Button
                    variant="ghost"
                    size="sm"
                    className="h-7 w-full text-xs"
                    onClick={() => handleFilterChange(filter.columnName, "")}
                  >
                    선택 초기화
                  </Button>
                </div>
              )}
            </PopoverContent>
          </Popover>
        );
      }

      default: // text
        return (
          <Input
            type="text"
            value={value}
            onChange={(e) => handleFilterChange(filter.columnName, e.target.value)}
            className="h-9 text-xs focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:outline-none sm:text-sm"
            style={{ width: `${width}px`, height: "36px", minHeight: "36px", outline: "none", boxShadow: "none" }}
            placeholder={column?.columnLabel}
          />
        );
    }
  };

  return (
    <div
      ref={containerRef}
      className="bg-card flex w-full flex-wrap items-center gap-2 border-b"
      style={{
        padding: component.style?.padding || "0.75rem",
        backgroundColor: component.style?.backgroundColor,
        minHeight: "48px",
      }}
    >
      {/* 필터 입력 필드들 */}
      {activeFilters.length > 0 && (
        <div className="flex flex-1 flex-wrap items-center gap-2">
          {activeFilters.map((filter) => (
            <div key={filter.columnName}>{renderFilterInput(filter)}</div>
          ))}

          {/* 초기화 버튼 */}
          <Button variant="outline" size="sm" onClick={handleResetFilters} className="h-9 shrink-0 text-xs sm:text-sm">
            <X className="mr-1 h-3 w-3 sm:h-4 sm:w-4" />
            초기화
          </Button>
        </div>
      )}

      {/* 필터가 없을 때는 빈 공간 */}
      {activeFilters.length === 0 && <div className="flex-1" />}

      {/* 오른쪽: 데이터 건수 + 설정 버튼들 (고정 모드에서는 숨김) */}
      <div className="flex flex-shrink-0 items-center gap-2">
        {/* 데이터 건수 표시 */}
        {currentTable?.dataCount !== undefined && (
          <div className="bg-muted text-muted-foreground rounded-md px-3 py-1.5 text-xs font-medium sm:text-sm">
            {currentTable.dataCount.toLocaleString()}건
          </div>
        )}

        {/* 동적 모드일 때만 설정 버튼 표시 (미리보기에서는 비활성화) */}
        {filterMode === "dynamic" && (
          <Button
            variant="outline"
            size="sm"
            onClick={() => !isPreviewMode && setSettingsOpen(true)}
            disabled={!selectedTableId || isPreviewMode}
            className="h-8 text-xs sm:h-9 sm:text-sm"
          >
            <Settings className="mr-1 h-3 w-3 sm:h-4 sm:w-4" />
            테이블 설정
          </Button>
        )}
      </div>

      {/* 통합 설정 모달 */}
      <TableSettingsModal
        isOpen={settingsOpen}
        onClose={() => setSettingsOpen(false)}
        onFiltersApplied={(filters) => setActiveFilters(filters)}
        screenId={screenId}
      />
    </div>
  );
}
