/**
 * UniversalListPage 타입 정의
 *
 * 59개 리스트 페이지를 통합하기 위한 config 기반 타입 시스템
 * 기존 기능 100% 유지, 테이블 영역만 공통화
 */

import { ReactNode } from 'react';
import { LucideIcon } from 'lucide-react';
import type { FilterFieldConfig, FilterValues } from '@/components/molecules/MobileFilter';
import type { ExcelColumn } from '@/lib/utils/excel-download';

// ===== 기본 타입 (IntegratedListTemplateV2에서 re-export) =====
export type { FilterFieldConfig, FilterValues };

export interface TabOption {
  value: string;
  label: string;
  mobileLabel?: string;
  count: number;
  color?: string;
}

export interface TableColumn {
  key: string;
  label: string;
  className?: string;
  hideOnMobile?: boolean;
  hideOnTablet?: boolean;
  /** 정렬 가능 여부 (기본값: true, NON_SORTABLE_KEYS에 해당하는 키는 자동 false) */
  sortable?: boolean;
  /** 셀 hover 시 복사 버튼 표시 (CopyableCell 래핑) */
  copyable?: boolean;
}

/**
 * 정렬이 불필요한 컬럼 키 목록
 * - 이 키들은 sortable 기본값이 false로 처리됨
 * - 명시적으로 sortable: true를 지정하면 오버라이드 가능
 */
export const NON_SORTABLE_KEYS = [
  'no',           // 번호 컬럼
  'rowNumber',    // 행 번호
  'actions',      // 작업 버튼
  'action',       // 작업 버튼 (단수)
  'checkbox',     // 체크박스
  'invoice',      // 거래명세서 버튼
  'setting',      // 설정 버튼
  'taxInvoice',   // 세금계산서 버튼
  'transactionStatement', // 거래명세서 발행 버튼
  'sourceDocument', // 연결문서 버튼
];

export interface StatCard {
  label: string;
  value: string | number;
  icon: LucideIcon;
  iconColor: string;
  onClick?: () => void;
  isActive?: boolean;
}

// ===== API 응답 타입 =====
export interface ListResult<T> {
  success: boolean;
  data?: T[];
  totalCount?: number;
  totalPages?: number;
  error?: string;
}

export interface DeleteResult {
  success: boolean;
  error?: string;
}

// ===== 액션 설정 =====
export interface ListActions<T> {
  /** 목록 조회 API */
  getList: (params?: ListParams) => Promise<ListResult<T>>;
  /** 단일 삭제 API (선택) */
  deleteItem?: (id: string) => Promise<DeleteResult>;
  /** 일괄 삭제 API (선택) */
  deleteBulk?: (ids: string[]) => Promise<DeleteResult>;
}

export interface ListParams {
  page?: number;
  pageSize?: number;
  search?: string;
  filters?: Record<string, string | string[]>;
  tab?: string;
  sortBy?: string;
  sortOrder?: 'asc' | 'desc';
}

// ===== 상세 보기 모드 =====
export type DetailMode = 'page' | 'modal' | 'none';

// ===== 커스텀 액션 버튼 =====
export interface CustomAction<T> {
  key: string;
  label: string;
  icon?: LucideIcon;
  variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
  /** 단일 아이템에 대한 액션 */
  onClick?: (item: T) => void | Promise<void>;
  /** 선택된 아이템들에 대한 일괄 액션 */
  onBulkClick?: (items: T[]) => void | Promise<void>;
  /** 액션 표시 조건 */
  showWhen?: 'always' | 'selected' | 'single-selected' | 'multi-selected';
  /** 확인 다이얼로그 표시 여부 */
  confirmDialog?: {
    title: string;
    description: string;
    confirmText?: string;
    cancelText?: string;
  };
}

// ===== 선택 핸들러 (renderTableRow, renderMobileCard에서 사용) =====
export interface SelectionHandlers {
  isSelected: boolean;
  onToggle: () => void;
}

// ===== 행 클릭 핸들러 =====
// Note: In renderTableRow/renderMobileCard, these handlers are pre-bound closures
// (item already captured by UniversalListPage), so the item parameter is optional.
export interface RowClickHandlers<T> {
  onRowClick?: (item?: T) => void;
  onEdit?: (item?: T) => void;
  onDelete?: (item?: T) => void;
}

// ===== 엑셀 다운로드 설정 =====
export interface ExcelDownloadConfig<T> {
  /** 엑셀 다운로드 활성화 여부 (기본: true) */
  enabled?: boolean;
  /** 엑셀 컬럼 정의 */
  columns: ExcelColumn<T>[];
  /** 파일명 (확장자 제외) */
  filename?: string;
  /** 시트명 */
  sheetName?: string;
  /**
   * 전체 데이터 조회 URL (서버 사이드 페이지네이션 시 필수)
   * - 예: '/api/proxy/items'
   * - size=10000 파라미터가 자동 추가됨
   */
  fetchAllUrl?: string;
  /**
   * 전체 데이터 조회 시 추가 파라미터 (동적)
   * - activeTab, filters 등 현재 상태 기반으로 파라미터 생성
   */
  fetchAllParams?: (params: {
    activeTab: string;
    filters: Record<string, string | string[]>;
    searchValue: string;
  }) => Record<string, string>;
  /**
   * API 응답을 데이터 배열로 변환
   * - 기본값: result.data?.data ?? result.data ?? []
   */
  mapResponse?: (response: unknown) => T[];
  /** 선택 항목 다운로드 활성화 (기본: true) */
  enableSelectedDownload?: boolean;
}

// ===== 메인 Config 타입 =====
export interface UniversalListConfig<T> {
  // ===== 페이지 기본 정보 =====
  /** 페이지 제목 */
  title: string;
  /** 페이지 설명 (선택) */
  description?: string;
  /** 페이지 아이콘 (선택) */
  icon?: LucideIcon;
  /** 기본 경로 (예: '/hr/employee-management') */
  basePath: string;

  // ===== ID 추출 =====
  /** 아이템에서 ID 추출 (string 키 또는 함수) */
  idField: keyof T | ((item: T) => string);

  // ===== API 액션 =====
  actions: ListActions<T>;

  // ===== 테이블 컬럼 =====
  columns: TableColumn[];
  /**
   * 탭별 다른 컬럼 구조 (columnsPerTab 설정 시 columns 대신 사용)
   * - key: 탭 value
   * - value: 해당 탭에서 사용할 컬럼 배열
   */
  columnsPerTab?: Record<string, TableColumn[]>;

  // ===== 필터 설정 =====
  /** 필터 필드 설정 */
  filterConfig?: FilterFieldConfig[];
  /** 필터 초기값 */
  initialFilters?: Record<string, string | string[]>;
  /** 필터 바텀시트 제목 (모바일) */
  filterTitle?: string;

  // ===== 탭 설정 =====
  /** 고정 탭 목록 */
  tabs?: TabOption[];
  /** 동적 탭 (API에서 가져오기) */
  fetchTabs?: () => Promise<TabOption[]>;
  /** 기본 활성 탭 */
  defaultTab?: string;
  /** 탭 렌더링 위치: 'card' (기본, 테이블 카드 내부) | 'above-stats' (통계 카드 위) */
  tabsPosition?: 'card' | 'above-stats';

  // ===== 통계 카드 =====
  /** 고정 통계 카드 */
  stats?: StatCard[];
  /** 동적 통계 (데이터 기반 계산) */
  computeStats?: (data: T[], totalCount: number) => StatCard[];

  // ===== 렌더링 함수 =====
  /** 테이블 행 렌더링 */
  renderTableRow: (
    item: T,
    index: number,
    globalIndex: number,
    handlers: SelectionHandlers & RowClickHandlers<T>
  ) => ReactNode;
  /** 모바일 카드 렌더링 */
  renderMobileCard: (
    item: T,
    index: number,
    globalIndex: number,
    handlers: SelectionHandlers & RowClickHandlers<T>
  ) => ReactNode;

  // ===== 상세 보기 설정 =====
  /** 상세 보기 모드 (기본: 'page') */
  detailMode?: DetailMode;
  /** 모달 모드일 때 사용할 모달 컴포넌트 */
  DetailModalComponent?: React.ComponentType<{
    isOpen: boolean;
    onClose: () => void;
    item: T | null;
    onRefresh?: () => void;
  }>;

  // ===== 커스텀 액션 =====
  /**
   * 헤더 액션 (선택 기반 동적 버튼 등)
   * - onCreate: 등록 버튼 클릭 핸들러
   * - selectedItems: 현재 선택된 아이템 ID Set
   * - onClearSelection: 선택 해제 함수
   * - onRefresh: 데이터 새로고침 함수
   */
  headerActions?: (params: {
    onCreate?: () => void;
    selectedItems: Set<string>;
    onClearSelection: () => void;
    onRefresh: () => void;
  }) => ReactNode;
  /**
   * 선택 액션 버튼 (테이블 왼쪽 "전체 N건 / N개 선택됨" 옆에 표시)
   * - 체크박스 선택 시에만 표시되는 버튼들 (상신, 승인, 삭제 등)
   * - headerActions에서 선택 의존 버튼을 분리하여 이쪽으로 이동
   */
  selectionActions?: (params: {
    selectedItems: Set<string>;
    onClearSelection: () => void;
    onRefresh: () => void;
  }) => ReactNode;
  /** 커스텀 액션 버튼 (상신, 승인 등) */
  customActions?: CustomAction<T>[];

  // ===== 공통 헤더 옵션 (달력/등록버튼) =====
  /**
   * 날짜 범위 선택기 (왼쪽 배치)
   * - enabled: 달력 표시 여부
   * - showPresets: 프리셋 버튼 (당해년도, 전전월, 전월, 당월, 어제, 오늘)
   * - startDate/endDate: 외부 상태 연동
   * - onChange: 날짜 변경 콜백
   */
  dateRangeSelector?: {
    enabled: boolean;
    showPresets?: boolean;
    /** 날짜 입력 숨김 (검색창만 표시하고 싶을 때) */
    hideDateInputs?: boolean;
    /** 표시할 프리셋 목록 */
    presets?: import('@/components/molecules/DateRangeSelector').DatePreset[];
    /** 프리셋 레이블 커스텀 오버라이드 */
    presetLabels?: Partial<Record<import('@/components/molecules/DateRangeSelector').DatePreset, string>>;
    /** 프리셋 버튼 위치: 'inline' (날짜 옆), 'below' (별도 줄) */
    presetsPosition?: 'inline' | 'below';
    /** 날짜 입력 변형: 'split' (DatePicker 2개), 'combined' (DateRangePicker 1개) */
    variant?: 'split' | 'combined';
    startDate?: string;
    endDate?: string;
    onStartDateChange?: (date: string) => void;
    onEndDateChange?: (date: string) => void;
    /** 추가 액션 (검색창 등) - presetsPosition이 'below'일 때 달력 옆에 배치됨 */
    extraActions?: ReactNode;
    /**
     * 날짜 필터링에 사용할 필드명 (clientSideFiltering: true 시 자동 필터링)
     * - 예: 'hireDate', 'createdAt', 'orderDate' 등
     * - 설정 시 startDate ~ endDate 범위로 해당 필드 자동 필터링
     */
    dateField?: string;
  };
  /**
   * 등록 버튼 (오른쪽 끝 배치)
   * - label: 버튼 텍스트 (예: '등록', '공정 등록')
   * - onClick: 클릭 핸들러
   * - icon: 아이콘 (기본: Plus)
   */
  createButton?: {
    label: string;
    onClick: () => void;
    icon?: LucideIcon;
  };

  // ===== 커스텀 테이블 헤더 =====
  /**
   * 동적 컬럼을 위한 커스텀 테이블 헤더 렌더링 (columns 대신 사용)
   * - displayData: 현재 페이지에 표시되는 데이터
   * - selectedItems: 선택된 아이템 ID Set
   * - onToggleSelectAll: 전체 선택/해제 핸들러
   */
  renderCustomTableHeader?: (params: {
    displayData: T[];
    selectedItems: Set<string>;
    onToggleSelectAll: () => void;
  }) => ReactNode;

  /** 데이터 변경 콜백 (동적 컬럼 계산 등에 사용) */
  onDataChange?: (data: T[]) => void;

  // ===== 엑셀 다운로드 =====
  /**
   * 엑셀 다운로드 설정
   * - 설정 시 헤더 액션에 자동으로 엑셀 다운로드 버튼 추가
   * - 클라이언트 사이드: 현재 데이터 기반 다운로드
   * - 서버 사이드: fetchAllUrl로 전체 데이터 조회 후 다운로드
   */
  excelDownload?: ExcelDownloadConfig<T>;

  // ===== 추가 옵션 =====
  /** 검색 플레이스홀더 */
  searchPlaceholder?: string;
  /** 검색창 숨김 */
  hideSearch?: boolean;
  /** 체크박스 표시 여부 (기본: true) */
  showCheckbox?: boolean;
  /** 번호 컬럼 표시 여부 (기본: true) */
  showRowNumber?: boolean;
  /** 페이지당 항목 수 (기본: 20) */
  itemsPerPage?: number;
  /** 삭제 확인 메시지 */
  deleteConfirmMessage?: {
    title?: string;
    description?: string;
  };

  // ===== 클라이언트 사이드 필터링 =====
  /**
   * 클라이언트 사이드 필터링 모드 (기본: false)
   * true인 경우 getList가 전체 데이터를 반환하고, 컴포넌트 내부에서 필터링/페이지네이션 처리
   */
  clientSideFiltering?: boolean;
  /** 검색 필터 함수 (클라이언트 사이드 + 서버 사이드 모드 모두 지원)
   * - clientSideFiltering: true → 기존 클라이언트 사이드 검색
   * - clientSideFiltering: false → 백엔드 검색 미지원 시 클라이언트 사이드 fallback 검색
   */
  searchFilter?: (item: T, searchValue: string) => boolean;
  /** 클라이언트 사이드 탭 필터 함수 */
  tabFilter?: (item: T, activeTab: string) => boolean;
  /** 커스텀 필터 함수 (filterConfig 기반 복잡한 필터링) */
  customFilterFn?: (items: T[], filterValues: Record<string, string | string[]>) => T[];
  /** 커스텀 정렬 함수 */
  customSortFn?: (items: T[], filterValues: Record<string, string | string[]>) => T[];
  /** 서버 사이드 정렬 콜백 (clientSideFiltering: false일 때 컬럼 헤더 클릭 시 호출) */
  onSortChange?: (sortBy: string | undefined, sortOrder: 'asc' | 'desc') => void;

  // ===== 테이블 헤더 액션 =====
  /** 테이블 헤더 우측 추가 액션 (총건, 필터 해제 버튼, 일괄 액션 등)
   * - ReactNode: 정적 콘텐츠
   * - 함수: 동적으로 params를 받아서 렌더링
   *   - totalCount: 총 데이터 수
   *   - selectedItems: 선택된 아이템 ID Set
   *   - onClearSelection: 선택 해제 함수
   */
  tableHeaderActions?: ReactNode | ((params: {
    totalCount: number;
    selectedItems: Set<string>;
    onClearSelection: () => void;
  }) => ReactNode);

  // ===== 추가 슬롯 =====
  /** 테이블 앞 커스텀 콘텐츠 (ReactNode 또는 selectedItems를 받는 함수) */
  beforeTableContent?: ReactNode | ((props: {
    selectedItems: Set<string>;
    onClearSelection: () => void;
  }) => ReactNode);
  /** 테이블 하단 푸터 */
  tableFooter?: ReactNode;
  /** 테이블 뒤에 표시될 컨텐츠 (캘린더 등) */
  afterTableContent?: ReactNode | ((props: { data: T[], selectedItems: Set<string> }) => ReactNode);
  /** 경고 배너 */
  alertBanner?: ReactNode;
  /** 헤더 액션 영역 아래, 검색 위 커스텀 탭 */
  tabsContent?: ReactNode;
  /** 추가 필터 (Select, DatePicker 등) */
  extraFilters?: ReactNode;
  /** 선택 항목 변경 콜백 (외부에서 선택 상태 동기화 필요 시) */
  onSelectionChange?: (selectedItems: Set<string>) => void;
  /** 검색어 변경 콜백 (config 내부에서 설정, 서버 사이드 검색용) */
  onSearchChange?: (search: string) => void;

  // ===== 컬럼 리사이즈 & 가시성 설정 =====
  /** 컬럼 설정 비활성화 (기본: false = 자동 활성화) */
  disableColumnSettings?: boolean;

  // ===== 커스텀 다이얼로그 슬롯 =====
  /**
   * 커스텀 다이얼로그 렌더링 (DocumentDetailModal, SalaryDetailDialog 등)
   * - data: 현재 표시 중인 데이터 배열
   * - selectedItems: 선택된 아이템 ID Set
   * - activeTab: 현재 활성 탭
   * - onRefresh: 데이터 새로고침 함수
   */
  renderDialogs?: (params: {
    data: T[];
    selectedItems: Set<string>;
    activeTab: string;
    onRefresh: () => void;
    getItemById: (id: string) => T | undefined;
  }) => ReactNode;
}

// ===== 외부 페이지네이션 설정 =====
export interface ExternalPagination {
  currentPage: number;
  totalPages: number;
  totalItems: number;
  itemsPerPage: number;
  onPageChange: (page: number) => void;
}

// ===== 외부 선택 상태 설정 =====
export interface ExternalSelection<T> {
  selectedItems: Set<string>;
  onToggleSelection: (id: string) => void;
  onToggleSelectAll: () => void;
  setSelectedItems?: (items: Set<string>) => void;
  getItemId: (item: T) => string;
}

// ===== 컴포넌트 Props =====
export interface UniversalListPageProps<T> {
  config: UniversalListConfig<T>;
  /** 초기 데이터 (SSR용, 선택) */
  initialData?: T[];
  /** 초기 총 개수 */
  initialTotalCount?: number;
  /**
   * 외부 페이지네이션 (서버 사이드 페이지네이션용)
   * - 설정 시 내부 페이지네이션 무시
   * - currentPage, totalPages, onPageChange 등 외부에서 관리
   */
  externalPagination?: ExternalPagination;
  /**
   * 외부 선택 상태 관리 (특수 행 타입이 있는 테이블용)
   * - 설정 시 내부 선택 상태 무시
   * - 선택 가능한 행만 필터링하는 로직은 외부에서 처리
   */
  externalSelection?: ExternalSelection<T>;
  /**
   * 탭 변경 콜백 (서버 사이드 필터링용)
   * - 설정 시 탭 변경 시 외부에 알림
   * - 외부에서 API 호출 후 데이터 갱신 가능
   */
  onTabChange?: (tab: string) => void;
  /**
   * 검색어 변경 콜백 (서버 사이드 검색용)
   * - 설정 시 검색어 변경 시 외부에 알림
   * - 외부에서 API 호출 후 데이터 갱신 가능
   */
  onSearchChange?: (search: string) => void;
  /**
   * 필터 변경 콜백 (서버 사이드 필터링용)
   * - 설정 시 필터 변경 시 외부에 알림
   * - 외부에서 API 호출 후 데이터 갱신 가능
   */
  onFilterChange?: (filters: Record<string, string | string[]>) => void;
  /**
   * 외부 로딩 상태 (서버 사이드 데이터 페칭용)
   * - 설정 시 내부 isLoading 대신 사용
   * - 부모 컴포넌트에서 데이터 로딩 상태를 직접 관리할 때 사용
   * - IntegratedListTemplateV2로 전달되어 스켈레톤 표시에 사용
   */
  externalIsLoading?: boolean;
  /**
   * 외부 검색 상태 관리
   * - 설정 시 내부 검색 상태 대신 외부에서 관리
   */
  externalSearch?: {
    searchValue: string;
    setSearchValue: (value: string) => void;
  };
  /**
   * 외부 필터 상태 관리
   * - 설정 시 내부 필터 상태 대신 외부에서 관리
   */
  externalFilter?: {
    filterValues: Record<string, string | string[]>;
    onFilterChange: (key: string, value: string | string[]) => void;
    onFilterReset: () => void;
  };
}

// ===== 내부 상태 타입 =====
export interface ListState<T> {
  data: T[];
  totalCount: number;
  totalPages: number;
  currentPage: number;
  isLoading: boolean;
  searchValue: string;
  selectedItems: Set<string>;
  activeTab: string;
  filters: Record<string, string | string[]>;
  tabs: TabOption[];
}
