/**
 * Search & Filter Utilities
 *
 * 클라이언트 사이드 검색/필터링 공통 유틸리티.
 * useMemo 내부의 반복적인 .filter() 체인을 선언적 파이프라인으로 대체.
 *
 * @example
 * const filtered = useMemo(() => applyFilters(data, [
 *   textFilter(searchQuery, ['vendorName', 'vendorCode', 'businessNumber']),
 *   enumFilter('category', categoryFilter),
 *   enumFilter('status', statusFilter),
 * ]), [data, searchQuery, categoryFilter, statusFilter]);
 */

// ===== Types =====

/** 필터 함수 타입 */
export type FilterFn<T> = (data: T[]) => T[];

/** 텍스트 검색 옵션 */
export interface TextFilterOptions {
  /** 대소문자 구분 여부 (기본값: false = case-insensitive) */
  caseSensitive?: boolean;
}

// ===== Core Filter Functions =====

/**
 * 텍스트 검색 필터
 *
 * 빈 query는 전체 반환 (short-circuit).
 * 기본 case-insensitive (한글에는 영향 없음).
 */
export function filterByText<T>(
  data: T[],
  query: string,
  fields: (keyof T & string)[],
  options?: TextFilterOptions
): T[] {
  if (!query || query.trim() === '') return data;

  const caseSensitive = options?.caseSensitive ?? false;
  const normalizedQuery = caseSensitive ? query : query.toLowerCase();

  return data.filter((item) =>
    fields.some((field) => {
      const value = item[field];
      if (value == null) return false;
      const str = String(value);
      return caseSensitive ? str.includes(normalizedQuery) : str.toLowerCase().includes(normalizedQuery);
    })
  );
}

/**
 * Enum 필터 (단일 값 매칭)
 *
 * allValue와 일치하면 전체 반환 (short-circuit).
 */
export function filterByEnum<T>(
  data: T[],
  field: keyof T & string,
  value: string,
  allValue: string = 'all'
): T[] {
  if (value === allValue) return data;
  const trimmedValue = value.trim();
  return data.filter((item) => String(item[field]).trim() === trimmedValue);
}

/**
 * 날짜 범위 필터 (YYYY-MM-DD 문자열 비교)
 *
 * startDate, endDate 모두 없으면 전체 반환.
 */
export function filterByDateRange<T>(
  data: T[],
  field: keyof T & string,
  startDate?: string,
  endDate?: string
): T[] {
  if (!startDate && !endDate) return data;

  return data.filter((item) => {
    const dateValue = String(item[field] ?? '');
    if (!dateValue) return false;
    if (startDate && dateValue < startDate) return false;
    if (endDate && dateValue > endDate) return false;
    return true;
  });
}

// ===== Pipeline =====

/**
 * 필터 파이프라인
 *
 * 여러 필터 함수를 순차 적용. 각 필터는 빈 데이터에 대해 short-circuit.
 */
export function applyFilters<T>(data: T[], filters: FilterFn<T>[]): T[] {
  return filters.reduce((result, filter) => {
    if (result.length === 0) return result;
    return filter(result);
  }, data);
}

// ===== Factory Functions (for applyFilters) =====

/**
 * textFilter 팩토리 — applyFilters용
 */
export function textFilter<T>(
  query: string,
  fields: (keyof T & string)[],
  options?: TextFilterOptions
): FilterFn<T> {
  return (data) => filterByText(data, query, fields, options);
}

/**
 * enumFilter 팩토리 — applyFilters용
 */
export function enumFilter<T>(
  field: keyof T & string,
  value: string,
  allValue: string = 'all'
): FilterFn<T> {
  return (data) => filterByEnum(data, field, value, allValue);
}

/**
 * dateRangeFilter 팩토리 — applyFilters용
 */
export function dateRangeFilter<T>(
  field: keyof T & string,
  startDate?: string,
  endDate?: string
): FilterFn<T> {
  return (data) => filterByDateRange(data, field, startDate, endDate);
}
