"use client";

/**
 * DynamicSearchFilter — 하드코딩 페이지용 공통 검색 필터 컴포넌트
 *
 * 기능:
 * - 사용자가 필터 컬럼을 자유롭게 추가/제거 (설정 모달)
 * - 필터 타입을 사용자가 텍스트/선택/날짜로 변경 가능
 * - 필터별 너비(%) 설정 가능
 * - 라벨은 placeholder로만 표시 (외부에 라벨 노출 없음)
 * - select 타입은 다중 선택 (체크박스)
 * - 날짜는 범위 선택 (FormDatePicker)
 * - 필터 설정 + 값을 localStorage에 저장 (페이지 새로고침 시 복원)
 * - 실시간 필터링 (값 변경 시 즉시 콜백 호출)
 * - 컬럼 라벨은 회사별 table_type_columns의 column_label 사용
 */

import React, { useState, useEffect, useCallback } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Checkbox } from "@/components/ui/checkbox";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { Settings, ChevronsUpDown, RotateCcw, Search, X } from "lucide-react";
import { cn } from "@/lib/utils";
import { apiClient } from "@/lib/api/client";
import { FormDatePicker } from "@/components/screen/filters/FormDatePicker";

// --- 타입 ---

export type FilterType = "text" | "select" | "date";

export interface FilterColumn {
  columnName: string;
  columnLabel: string;
  /** 원본 inputType (DB에서 가져온 값, 타입 변경 시 기본값 복원용) */
  originalType: FilterType;
  /** 사용자가 선택한 필터 타입 */
  filterType: FilterType;
  enabled: boolean;
  /** 필터 너비 (%, 10~100, 기본 25) */
  width: number;
}

export interface FilterValue {
  columnName: string;
  operator: "contains" | "equals" | "in" | "between";
  value: string;
}

export interface ExternalFilterConfig {
  columnName: string;
  displayName: string;
  enabled: boolean;
  filterType: FilterType;
  width: number;
}

export interface DynamicSearchFilterProps {
  /** 테이블명 (컬럼 목록 + 카테고리 옵션 로드에 사용) */
  tableName: string;
  /** 고유 ID (localStorage 키 분리용, 예: "item-info", "sales-order") */
  filterId: string;
  /** 필터 변경 시 콜백 — API 필터 배열 형태로 전달 */
  onFilterChange: (filters: FilterValue[]) => void;
  /** 데이터 건수 표시 (optional) */
  dataCount?: number;
  /** 추가 액션 버튼 영역 */
  extraActions?: React.ReactNode;
  /** TableSettingsModal에서 전달된 외부 필터 설정 (제공 시 자체 설정 모달 숨김) */
  externalFilterConfig?: ExternalFilterConfig[];
}

const FILTER_TYPE_OPTIONS: { value: FilterType; label: string }[] = [
  { value: "text", label: "텍스트" },
  { value: "select", label: "선택" },
  { value: "date", label: "날짜" },
];

const WIDTH_OPTIONS = [
  { value: 15, label: "15%" },
  { value: 20, label: "20%" },
  { value: 25, label: "25%" },
  { value: 30, label: "30%" },
  { value: 40, label: "40%" },
  { value: 50, label: "50%" },
];

// --- 컴포넌트 ---

export function DynamicSearchFilter({
  tableName,
  filterId,
  onFilterChange,
  dataCount,
  extraActions,
  externalFilterConfig,
}: DynamicSearchFilterProps) {
  const [allColumns, setAllColumns] = useState<FilterColumn[]>([]);
  const [activeFilters, setActiveFilters] = useState<FilterColumn[]>([]);
  const [filterValues, setFilterValues] = useState<Record<string, any>>({});
  const [selectOptions, setSelectOptions] = useState<Record<string, { label: string; value: string }[]>>({});
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [selectSearchTerms, setSelectSearchTerms] = useState<Record<string, string>>({});
  const [tempColumns, setTempColumns] = useState<FilterColumn[]>([]);

  const STORAGE_KEY_FILTERS = `dynamic_filter_config_${filterId}`;
  const STORAGE_KEY_VALUES = `dynamic_filter_values_${filterId}`;

  // 컬럼 정보 로드 (회사별 table_type_columns의 column_label 사용)
  useEffect(() => {
    const loadColumns = async () => {
      try {
        const res = await apiClient.get(`/table-management/tables/${tableName}/web-types`);
        const types = res.data?.data || [];

        const AUTO_COLS = ["id", "created_date", "updated_date", "writer", "company_code"];
        const cols: FilterColumn[] = types
          .filter((t: any) => !AUTO_COLS.includes(t.columnName))
          .map((t: any) => {
            let filterType: FilterType = "text";
            if (t.inputType === "category" || t.inputType === "select") filterType = "select";
            else if (t.inputType === "date" || t.inputType === "datetime") filterType = "date";
            return {
              columnName: t.columnName,
              columnLabel: t.displayName || t.columnLabel || t.columnName,
              originalType: filterType,
              filterType,
              enabled: false,
              width: 25,
            };
          });

        // localStorage에서 저장된 설정 복원 (enabled, filterType, width)
        const saved = localStorage.getItem(STORAGE_KEY_FILTERS);
        let merged = cols;
        if (saved) {
          try {
            const parsed = JSON.parse(saved) as FilterColumn[];
            merged = cols.map((col) => {
              const s = parsed.find((p) => p.columnName === col.columnName);
              return s ? { ...col, enabled: s.enabled, filterType: s.filterType, width: s.width || 25 } : col;
            });
          } catch { /* skip */ }
        }

        setAllColumns(merged);
        // externalFilterConfig가 있으면 외부 설정이 activeFilters를 관리하므로 건드리지 않음
        if (!externalFilterConfig) {
          setActiveFilters(merged.filter((c) => c.enabled));
        }

        // 저장된 필터 값 복원
        const savedValues = localStorage.getItem(STORAGE_KEY_VALUES);
        if (savedValues) {
          try { setFilterValues(JSON.parse(savedValues)); } catch { /* skip */ }
        }
      } catch (err) {
        console.error("필터 컬럼 로드 실패:", err);
      }
    };
    loadColumns();
  }, [tableName, STORAGE_KEY_FILTERS, STORAGE_KEY_VALUES]);

  // 외부 필터 설정 적용 (TableSettingsModal에서 전달)
  useEffect(() => {
    if (!externalFilterConfig) return;
    const active: FilterColumn[] = externalFilterConfig
      .filter((f) => f.enabled)
      .map((f) => ({
        columnName: f.columnName,
        columnLabel: f.displayName,
        originalType: f.filterType,
        filterType: f.filterType,
        enabled: true,
        width: f.width,
      }));
    setActiveFilters(active);
    // allColumns도 동기화하여 설정 모달에서 일관된 상태 표시
    setAllColumns((prev) =>
      prev.map((col) => {
        const ext = externalFilterConfig.find((f) => f.columnName === col.columnName);
        return ext ? { ...col, enabled: ext.enabled, filterType: ext.filterType, width: ext.width } : col;
      })
    );
  }, [externalFilterConfig]);

  // select 타입 필터의 옵션 로드 (카테고리 → 없으면 실제 데이터 distinct)
  useEffect(() => {
    const loadOptions = async () => {
      const selectCols = activeFilters.filter((f) => f.filterType === "select");
      if (selectCols.length === 0) return;

      const opts: Record<string, { label: string; value: string }[]> = {};
      const flatten = (vals: any[]): { label: string; value: string }[] => {
        const result: { label: string; value: string }[] = [];
        for (const v of vals) {
          result.push({ value: v.valueCode, label: v.valueLabel });
          if (v.children?.length) result.push(...flatten(v.children));
        }
        return result;
      };

      await Promise.all(
        selectCols.map(async (col) => {
          if (selectOptions[col.columnName]?.length) return; // 이미 로드됨
          try {
            // 1차: 카테고리 옵션 로드
            const res = await apiClient.get(`/table-categories/${tableName}/${col.columnName}/values`);
            if (res.data?.success && res.data.data?.length > 0) {
              opts[col.columnName] = flatten(res.data.data);
              return;
            }
          } catch { /* skip */ }

          // 2차: 카테고리 없으면 실제 데이터에서 distinct 값 추출
          try {
            const dataRes = await apiClient.post(`/table-management/tables/${tableName}/data`, {
              page: 1, size: 5000, autoFilter: true,
            });
            const rawData = dataRes.data?.data;
            const rows = Array.isArray(rawData) ? rawData : (rawData?.data || rawData?.rows || []);
            const uniqueValues = new Set<string>();
            for (const row of rows) {
              const val = row[col.columnName];
              if (val != null && String(val).trim() !== "") {
                uniqueValues.add(String(val));
              }
            }
            if (uniqueValues.size > 0) {
              const sorted = [...uniqueValues].sort();
              opts[col.columnName] = sorted.map((v) => ({ label: v, value: v }));
            }
          } catch (err) {
            console.warn(`[DynamicSearchFilter] ${col.columnName} distinct 로드 실패:`, err);
          }
        })
      );
      if (Object.keys(opts).length > 0) {
        setSelectOptions((prev) => ({ ...prev, ...opts }));
      }
    };
    loadOptions();
  }, [activeFilters, tableName]); // eslint-disable-line react-hooks/exhaustive-deps

  // 필터 값 → API 필터 형태로 변환
  const emitFilters = useCallback((values: Record<string, any>) => {
    const filters: FilterValue[] = [];
    for (const f of activeFilters) {
      const val = values[f.columnName];
      if (!val || (typeof val === "string" && val === "")) continue;

      if (f.filterType === "date" && typeof val === "object" && (val.from || val.to)) {
        const from = val.from || "";
        const to = val.to || "";
        if (from || to) filters.push({ columnName: f.columnName, operator: "between", value: `${from}|${to}` });
      } else if (Array.isArray(val)) {
        if (val.length > 0) filters.push({ columnName: f.columnName, operator: "in", value: val.join("|") });
      } else {
        filters.push({
          columnName: f.columnName,
          operator: f.filterType === "select" ? "equals" : "contains",
          value: String(val),
        });
      }
    }
    onFilterChange(filters);
  }, [activeFilters, onFilterChange]);

  const handleValueChange = (columnName: string, value: any) => {
    const newValues = { ...filterValues, [columnName]: value };
    setFilterValues(newValues);
    localStorage.setItem(STORAGE_KEY_VALUES, JSON.stringify(newValues));
    emitFilters(newValues);
  };

  // 초기 로드 시 필터 적용
  useEffect(() => {
    if (activeFilters.length > 0 && Object.keys(filterValues).length > 0) {
      emitFilters(filterValues);
    }
  }, [activeFilters.length]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleReset = () => {
    setFilterValues({});
    localStorage.removeItem(STORAGE_KEY_VALUES);
    onFilterChange([]);
  };

  // 설정 모달
  const openSettings = () => {
    setTempColumns(allColumns.map((c) => ({ ...c })));
    setSettingsOpen(true);
  };

  const saveSettings = () => {
    setAllColumns(tempColumns);
    const active = tempColumns.filter((c) => c.enabled);
    setActiveFilters(active);
    localStorage.setItem(STORAGE_KEY_FILTERS, JSON.stringify(tempColumns));

    // 비활성화된 필터 값 + 타입 변경된 필터 값 제거
    const activeNames = new Set(active.map((a) => a.columnName));
    const cleaned = { ...filterValues };
    for (const key of Object.keys(cleaned)) {
      if (!activeNames.has(key)) delete cleaned[key];
    }
    // 타입이 변경된 필터의 값도 초기화
    for (const col of active) {
      const prev = allColumns.find((c) => c.columnName === col.columnName);
      if (prev && prev.filterType !== col.filterType) {
        delete cleaned[col.columnName];
      }
    }
    setFilterValues(cleaned);
    localStorage.setItem(STORAGE_KEY_VALUES, JSON.stringify(cleaned));

    setSettingsOpen(false);
    emitFilters(cleaned);
  };

  // --- 필터 렌더링 (라벨은 placeholder로만) ---

  const renderFilterInput = (filter: FilterColumn) => {
    const value = filterValues[filter.columnName] || "";
    const widthStyle = { flex: `0 0 ${filter.width}%`, minWidth: "120px" };

    switch (filter.filterType) {
      case "date":
        return (
          <div style={widthStyle} className="flex items-center gap-1">
            <div className="flex-1">
              <FormDatePicker
                value={typeof value === "object" ? value.from || "" : ""}
                onChange={(v) => handleValueChange(filter.columnName, { ...((typeof value === "object" && value) || {}), from: v })}
                placeholder={`${filter.columnLabel} 시작`}
              />
            </div>
            <span className="text-muted-foreground text-xs shrink-0">~</span>
            <div className="flex-1">
              <FormDatePicker
                value={typeof value === "object" ? value.to || "" : ""}
                onChange={(v) => handleValueChange(filter.columnName, { ...((typeof value === "object" && value) || {}), to: v })}
                placeholder={`${filter.columnLabel} 종료`}
              />
            </div>
          </div>
        );

      case "select": {
        const options = selectOptions[filter.columnName] || [];
        const selectedValues: string[] = Array.isArray(value) ? value : value ? [value] : [];

        const getDisplayText = () => {
          if (selectedValues.length === 0) return filter.columnLabel;
          if (selectedValues.length === 1) {
            const opt = options.find((o) => o.value === selectedValues[0]);
            return opt?.label || selectedValues[0];
          }
          return `${filter.columnLabel} (${selectedValues.length})`;
        };

        const toggleOption = (optValue: string, checked: boolean) => {
          const next = checked ? [...selectedValues, optValue] : selectedValues.filter((v) => v !== optValue);
          handleValueChange(filter.columnName, next.length > 0 ? next : "");
        };

        const searchTerm = (selectSearchTerms[filter.columnName] || "").toLowerCase();
        const filteredOptions = searchTerm
          ? options.filter((opt) => opt.label.toLowerCase().includes(searchTerm))
          : options;

        return (
          <div style={widthStyle}>
            <Popover onOpenChange={(open) => {
              if (!open) {
                setSelectSearchTerms((prev) => {
                  const next = { ...prev };
                  delete next[filter.columnName];
                  return next;
                });
              }
            }}>
              <PopoverTrigger asChild>
                <Button variant="outline" role="combobox"
                  className={cn("h-9 w-full justify-between text-sm font-normal", selectedValues.length === 0 && "text-muted-foreground")}>
                  <span className="truncate">{getDisplayText()}</span>
                  <ChevronsUpDown className="ml-1 h-3.5 w-3.5 shrink-0 opacity-50" />
                </Button>
              </PopoverTrigger>
              <PopoverContent className="p-0" style={{ minWidth: "var(--radix-popover-trigger-width)", width: "auto", maxWidth: "400px" }} align="start">
                {options.length > 0 && (
                  <div className="border-b p-1">
                    <div className="relative">
                      <Search className="text-muted-foreground absolute left-2 top-1/2 h-3 w-3 -translate-y-1/2" />
                      <Input
                        value={selectSearchTerms[filter.columnName] || ""}
                        onChange={(e) =>
                          setSelectSearchTerms((prev) => ({ ...prev, [filter.columnName]: e.target.value }))
                        }
                        placeholder="검색..."
                        className="h-7 pl-7 pr-7 text-xs"
                      />
                      {selectSearchTerms[filter.columnName] && (
                        <button
                          onClick={() =>
                            setSelectSearchTerms((prev) => ({ ...prev, [filter.columnName]: "" }))
                          }
                          className="absolute right-2 top-1/2 -translate-y-1/2"
                        >
                          <X className="text-muted-foreground hover:text-foreground h-3 w-3" />
                        </button>
                      )}
                    </div>
                  </div>
                )}
                <div className="max-h-60 overflow-auto p-1">
                  {options.length === 0 ? (
                    <div className="text-muted-foreground px-3 py-2 text-xs">옵션 없음</div>
                  ) : filteredOptions.length === 0 ? (
                    <div className="text-muted-foreground px-3 py-2 text-xs">검색 결과 없음</div>
                  ) : filteredOptions.map((opt, i) => (
                    <div key={`${opt.value}-${i}`}
                      className="hover:bg-accent flex cursor-pointer items-center space-x-2 rounded-sm px-2 py-1.5"
                      onClick={() => toggleOption(opt.value, !selectedValues.includes(opt.value))}>
                      <Checkbox checked={selectedValues.includes(opt.value)} />
                      <span className="truncate text-sm">{opt.label}</span>
                    </div>
                  ))}
                </div>
                {selectedValues.length > 0 && (
                  <div className="border-t p-1">
                    <Button variant="ghost" size="sm" className="h-7 w-full text-xs"
                      onClick={() => handleValueChange(filter.columnName, "")}>선택 초기화</Button>
                  </div>
                )}
              </PopoverContent>
            </Popover>
          </div>
        );
      }

      default: // text
        return (
          <div style={widthStyle}>
            <Input type="text" value={value}
              onChange={(e) => handleValueChange(filter.columnName, e.target.value)}
              onKeyDown={(e) => { if (e.key === "Enter") emitFilters(filterValues); }}
              className="h-9 w-full text-sm" placeholder={filter.columnLabel} />
          </div>
        );
    }
  };

  return (
    <div className="bg-card flex w-full flex-wrap items-center gap-2 rounded-lg border p-3 shadow-sm">
      {/* 활성 필터들 — 라벨 없이 placeholder만 */}
      {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={handleReset} className="h-9 shrink-0">
            <RotateCcw className="mr-1 h-3.5 w-3.5" /> 초기화
          </Button>
        </div>
      ) : (
        <div className="flex-1 text-sm text-muted-foreground">
          검색 필터를 설정해주세요
        </div>
      )}

      {/* 우측 */}
      <div className="flex items-center gap-2 shrink-0">
        {dataCount !== undefined && (
          <div className="bg-muted text-muted-foreground rounded-md px-3 py-1.5 text-sm font-medium">
            {dataCount.toLocaleString()}건
          </div>
        )}
        {extraActions}
        {!externalFilterConfig && (
          <Button variant="outline" size="sm" onClick={openSettings} className="h-9">
            <Settings className="mr-1 h-3.5 w-3.5" /> 필터 설정
          </Button>
        )}
      </div>

      {/* 필터 설정 모달 */}
      <Dialog open={settingsOpen} onOpenChange={setSettingsOpen}>
        <DialogContent className="max-w-2xl max-h-[70vh] overflow-auto">
          <DialogHeader>
            <DialogTitle>검색 필터 설정</DialogTitle>
          </DialogHeader>
          <div className="py-2">
            {/* 헤더 */}
            <div className="flex items-center gap-3 pb-2 border-b mb-1 text-xs font-medium text-muted-foreground">
              <div className="w-8 text-center">활성</div>
              <div className="flex-1">컬럼명</div>
              <div className="w-[120px]">필터 타입</div>
              <div className="w-[100px]">너비</div>
            </div>
            {tempColumns.map((col, idx) => (
              <div key={col.columnName} className="flex items-center gap-3 py-1.5 px-1 hover:bg-muted/50 rounded">
                <div className="w-8 text-center">
                  <Checkbox
                    checked={col.enabled}
                    onCheckedChange={(checked) => {
                      const next = [...tempColumns];
                      next[idx] = { ...next[idx], enabled: !!checked };
                      setTempColumns(next);
                    }}
                  />
                </div>
                <div className="flex-1 text-sm">{col.columnLabel}</div>
                <div className="w-[120px]">
                  <Select
                    value={col.filterType}
                    onValueChange={(v) => {
                      const next = [...tempColumns];
                      next[idx] = { ...next[idx], filterType: v as FilterType };
                      setTempColumns(next);
                    }}
                  >
                    <SelectTrigger className="h-8 text-xs">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      {FILTER_TYPE_OPTIONS.map((opt) => (
                        <SelectItem key={opt.value} value={opt.value}>{opt.label}</SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
                <div className="w-[100px]">
                  <Select
                    value={String(col.width)}
                    onValueChange={(v) => {
                      const next = [...tempColumns];
                      next[idx] = { ...next[idx], width: Number(v) };
                      setTempColumns(next);
                    }}
                  >
                    <SelectTrigger className="h-8 text-xs">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      {WIDTH_OPTIONS.map((opt) => (
                        <SelectItem key={opt.value} value={String(opt.value)}>{opt.label}</SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
              </div>
            ))}
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setSettingsOpen(false)}>취소</Button>
            <Button onClick={saveSettings}>적용</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
