'use client';

import { useState, useMemo, useCallback, useEffect, useRef } from 'react';
import { invalidateDashboard } from '@/lib/dashboard-invalidation';
import { format } from 'date-fns';
import { useDateRange } from '@/hooks';
import {
  Plus,
  Calendar,
  Check,
  X,
  Clock,
  Heart,
  TrendingUp,
} from 'lucide-react';
import {
  getLeaves,
  getLeaveBalances,
  getLeaveGrants,
  createLeave,
  createLeaveGrant,
  approveLeavesMany,
  rejectLeavesMany,
  type LeaveRecord,
  type LeaveBalanceRecord,
  type LeaveGrantRecord,
  type LeaveGrantType,
} from './actions';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Badge } from '@/components/ui/badge';
import { TableRow, TableCell } from '@/components/ui/table';
import { ConfirmDialog } from '@/components/ui/confirm-dialog';
import {
  UniversalListPage,
  type UniversalListConfig,
  type TableColumn,
  type StatCard,
  type TabOption,
  type FilterFieldConfig,
  type FilterValues,
} from '@/components/templates/UniversalListPage';
import { ListMobileCard, InfoField } from '@/components/organisms/MobileCard';
import { VacationGrantDialog } from './VacationGrantDialog';
import { VacationRequestDialog } from './VacationRequestDialog';
import type {
  MainTabType,
  VacationUsageRecord,
  VacationGrantRecord,
  VacationRequestRecord,
  SortOption,
  FilterOption,
  VacationType,
  RequestStatus,
} from './types';
import {
  MAIN_TAB_LABELS,
  SORT_OPTIONS,
  FILTER_OPTIONS,
  VACATION_TYPE_LABELS,
  REQUEST_STATUS_LABELS,
  REQUEST_STATUS_COLORS,
} from './types';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { toast } from 'sonner';
import { formatDate } from '@/lib/utils/date';

// ===== Mock 데이터 생성 (request 탭용 - 신청 현황은 leaves API 사용 예정) =====

const _generateRequestData = (): VacationRequestRecord[] => {
  const departments = ['개발팀', '디자인팀', '기획팀', '영업팀', '인사팀'];
  const positions = ['팀장', '파트장', '선임', '주임', '사원'];
  const ranks = ['부장', '차장', '과장', '대리', '사원'];
  const statuses: RequestStatus[] = ['pending', 'approved', 'rejected'];

  return Array.from({ length: 7 }, (_, i) => {
    const startDate = new Date(2025, 11, (i % 28) + 1);
    const endDate = new Date(startDate);
    endDate.setDate(endDate.getDate() + Math.floor(Math.random() * 5) + 1);

    return {
      id: `request-${i + 1}`,
      employeeId: `EMP${String(i + 1).padStart(3, '0')}`,
      employeeName: ['김철수', '이영희', '박민수', '정수진', '최동현', '강미영', '윤상호'][i],
      department: departments[i % departments.length],
      position: positions[i % positions.length],
      rank: ranks[i % ranks.length],
      startDate: format(startDate, 'yyyy-MM-dd'),
      endDate: format(endDate, 'yyyy-MM-dd'),
      vacationDays: Math.floor(Math.random() * 5) + 1,
      status: statuses[i % statuses.length],
      requestDate: format(new Date(2025, 11, i + 1), 'yyyy-MM-dd'),
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
    };
  });
};

export function VacationManagement() {
  // ===== 상태 관리 =====
  const [mainTab, setMainTab] = useState<MainTabType>('usage');
  const [searchQuery, setSearchQuery] = useState('');
  const [filterOption, setFilterOption] = useState<FilterOption>('all');
  const [sortOption, setSortOption] = useState<SortOption>('rank');
  const [selectedItems, setSelectedItems] = useState<Set<string>>(new Set());
  const itemsPerPage = 20;

  // 날짜 범위 상태 (input type="date" 용)
  const { startDate, endDate, setStartDate, setEndDate } = useDateRange('currentMonth');

  // 다이얼로그 상태
  const [grantDialogOpen, setGrantDialogOpen] = useState(false);
  const [requestDialogOpen, setRequestDialogOpen] = useState(false);
  const [approveDialogOpen, setApproveDialogOpen] = useState(false);
  const [rejectDialogOpen, setRejectDialogOpen] = useState(false);

  // 로딩/처리중 상태
  const [isLoading, setIsLoading] = useState(false);
  const isInitialLoadDone = useRef(false);
  const [isProcessing, setIsProcessing] = useState(false);

  // 데이터 상태 (usage/grant 탭은 API, request는 Mock)
  const [usageData, setUsageData] = useState<VacationUsageRecord[]>([]);
  const [grantData, setGrantData] = useState<VacationGrantRecord[]>([]);
  const [requestData, setRequestData] = useState<VacationRequestRecord[]>([]);
  const [, setApiLeaveRecords] = useState<LeaveRecord[]>([]);

  // ===== API 데이터 로드 =====
  /**
   * 휴가 사용현황 데이터 로드 (usage 탭)
   */
  const fetchUsageData = useCallback(async () => {
    if (!isInitialLoadDone.current) {
      setIsLoading(true);
    }
    try {
      const currentYear = new Date().getFullYear();
      const result = await getLeaveBalances({ year: currentYear, perPage: 100 });
      if (result.success && result.data) {
        // API 데이터를 VacationUsageRecord 형식으로 변환
        // 사원관리와 동일: 직책=job_title_label, 직급=json_extra.rank
        const converted: VacationUsageRecord[] = result.data.items.map((item: LeaveBalanceRecord) => ({
          id: String(item.id),
          employeeId: String(item.userId),
          employeeName: item.displayName || item.employeeName,
          department: item.department,
          position: item.jobTitle || '-',  // job_title_label → 직책
          rank: item.rank || '-',          // json_extra.rank → 직급
          hireDate: item.hireDate || '-',
          baseVacation: '15일', // 기본 연차
          grantedVacation: `${Math.max(0, item.totalDays - 15)}일`, // 부여일수 = 총일수 - 기본15일
          usedVacation: `${item.usedDays}일`,
          remainingVacation: `${item.remainingDays}일`,
          annual: { total: item.totalDays, used: item.usedDays, remaining: item.remainingDays },
          monthly: { total: 0, used: 0, remaining: 0 },
          reward: { total: 0, used: 0, remaining: 0 },
          other: { total: 0, used: 0, remaining: 0 },
          createdAt: new Date().toISOString(),
          updatedAt: new Date().toISOString(),
        }));
        setUsageData(converted);
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      console.error('[VacationManagement] fetchUsageData error:', error);
    } finally {
      setIsLoading(false);
      isInitialLoadDone.current = true;
    }
  }, []);

  /**
   * 휴가 부여현황 데이터 로드 (grant 탭)
   */
  const fetchGrantData = useCallback(async () => {
    if (!isInitialLoadDone.current) {
      setIsLoading(true);
    }
    try {
      const currentYear = new Date().getFullYear();
      const result = await getLeaveGrants({ year: currentYear, perPage: 100 });
      if (result.success && result.data) {
        // API 데이터를 VacationGrantRecord 형식으로 변환
        // 사원관리와 동일: 직책=job_title_label, 직급=json_extra.rank
        const converted: VacationGrantRecord[] = result.data.items.map((item: LeaveGrantRecord) => ({
          id: String(item.id),
          employeeId: String(item.userId),
          employeeName: item.employeeName,
          department: item.department,
          position: item.jobTitle || '-',  // job_title_label → 직책
          rank: item.rank || '-',          // json_extra.rank → 직급
          vacationType: item.grantType as VacationType,
          grantDate: formatDate(item.grantDate),
          grantDays: item.grantDays,
          reason: item.reason || undefined,
          createdAt: item.createdAt,
          updatedAt: item.createdAt,
        }));
        setGrantData(converted);
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      console.error('[VacationManagement] fetchGrantData error:', error);
    } finally {
      setIsLoading(false);
      isInitialLoadDone.current = true;
    }
  }, []);

  /**
   * 휴가 신청현황 데이터 로드 (request 탭)
   */
  const fetchLeaveRequests = useCallback(async () => {
    if (!isInitialLoadDone.current) {
      setIsLoading(true);
    }
    try {
      const result = await getLeaves({
        dateFrom: startDate,
        dateTo: endDate,
        perPage: 100,
      });
      if (result.success && result.data) {
        setApiLeaveRecords(result.data.items);
        // API 데이터를 VacationRequestRecord 형식으로 변환
        // position = 직책 (팀장, 팀원), rank = 직급 (부장, 과장)
        const converted: VacationRequestRecord[] = result.data.items.map((item) => {
          const profile = item.userProfile;
          return {
            id: String(item.id),
            employeeId: String(item.userId),
            employeeName: item.user?.name || '알 수 없음',
            department: profile?.department?.name || '-',
            position: profile?.job_title_label || '-',   // job_title_label → 직책
            rank: profile?.rank || '-',                  // json_extra.rank → 직급 (사원관리와 동일)
            startDate: item.startDate,
            endDate: item.endDate,
            vacationDays: item.days,
            status: item.status as RequestStatus,
            requestDate: formatDate(item.createdAt),
            createdAt: item.createdAt,
            updatedAt: item.updatedAt,
          };
        });
        setRequestData(converted);
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      console.error('[VacationManagement] fetchLeaveRequests error:', error);
    } finally {
      setIsLoading(false);
      isInitialLoadDone.current = true;
    }
  }, [startDate, endDate]);

  // 초기 데이터 로드
  useEffect(() => {
    fetchUsageData();
    fetchGrantData();
    fetchLeaveRequests();
  }, [fetchUsageData, fetchGrantData, fetchLeaveRequests]);

  // ===== 탭 변경 핸들러 =====
  const handleMainTabChange = useCallback((value: string) => {
    setMainTab(value as MainTabType);
    setSelectedItems(new Set());
    setSearchQuery('');
  }, []);

  // ===== 필터링된 데이터 =====
  const filteredUsageData = useMemo(() => {
    return usageData.filter(item =>
      item.employeeName.includes(searchQuery) ||
      item.department.includes(searchQuery)
    );
  }, [usageData, searchQuery]);

  const filteredGrantData = useMemo(() => {
    return grantData.filter(item =>
      item.employeeName.includes(searchQuery) ||
      item.department.includes(searchQuery)
    );
  }, [grantData, searchQuery]);

  const filteredRequestData = useMemo(() => {
    return requestData.filter(item =>
      item.employeeName.includes(searchQuery) ||
      item.department.includes(searchQuery)
    );
  }, [requestData, searchQuery]);

  // ===== 현재 탭 데이터 =====
  const currentData = useMemo(() => {
    switch (mainTab) {
      case 'usage': return filteredUsageData;
      case 'grant': return filteredGrantData;
      case 'request': return filteredRequestData;
      default: return [];
    }
  }, [mainTab, filteredUsageData, filteredGrantData, filteredRequestData]);

  // ===== 승인/거절 핸들러 =====
  const handleApproveClick = useCallback((selected: Set<string>) => {
    // 버튼 클릭 시 UniversalListPage의 선택 상태를 내부 state로 복사
    setSelectedItems(selected);
    setApproveDialogOpen(true);
  }, []);

  const handleApproveConfirm = useCallback(async () => {
    if (isProcessing) return;
    setIsProcessing(true);
    try {
      const ids = Array.from(selectedItems).map((id) => parseInt(id, 10));
      const result = await approveLeavesMany(ids);
      if (result.success) {
        invalidateDashboard('leave');
        await fetchLeaveRequests();
        await fetchUsageData(); // 휴가 사용현황도 갱신
      } else {
        console.error('[VacationManagement] 승인 실패:', result.error);
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      console.error('[VacationManagement] handleApproveConfirm error:', error);
    } finally {
      setSelectedItems(new Set());
      setApproveDialogOpen(false);
      setIsProcessing(false);
    }
  }, [selectedItems, isProcessing, fetchLeaveRequests, fetchUsageData]);

  const handleRejectClick = useCallback((selected: Set<string>) => {
    // 버튼 클릭 시 UniversalListPage의 선택 상태를 내부 state로 복사
    setSelectedItems(selected);
    setRejectDialogOpen(true);
  }, []);

  const handleRejectConfirm = useCallback(async () => {
    if (isProcessing) return;
    setIsProcessing(true);
    try {
      const ids = Array.from(selectedItems).map((id) => parseInt(id, 10));
      const result = await rejectLeavesMany(ids, '관리자에 의해 반려됨');
      if (result.success) {
        invalidateDashboard('leave');
        await fetchLeaveRequests();
      } else {
        console.error('[VacationManagement] 반려 실패:', result.error);
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      console.error('[VacationManagement] handleRejectConfirm error:', error);
    } finally {
      setSelectedItems(new Set());
      setRejectDialogOpen(false);
      setIsProcessing(false);
    }
  }, [selectedItems, isProcessing, fetchLeaveRequests]);

  // ===== 통계 카드 (기획서: 휴가 승인 대기, 연차, 경조사, 연간 연차 사용률) =====
  const statCards: StatCard[] = useMemo(() => {
    // 휴가 승인 대기 (pending 상태인 request 수)
    const pendingCount = requestData.filter(r => r.status === 'pending').length;

    // 연차 사용자 수
    const annualCount = usageData.length;

    // 경조사 휴가 수
    const condolenceCount = grantData.filter(g => g.vacationType === 'condolence').length;

    // 연간 연차 사용률 계산 (총 사용일 / 총 부여일 * 100)
    const totalUsed = usageData.reduce((sum, u) => sum + u.annual.used, 0);
    const totalAvailable = usageData.reduce((sum, u) => sum + u.annual.total, 0);
    const usageRate = totalAvailable > 0 ? ((totalUsed / totalAvailable) * 100).toFixed(1) : '0.0';

    return [
      { label: '휴가 승인 대기', value: `${pendingCount}명`, icon: Clock, iconColor: 'text-yellow-500' },
      { label: '연차', value: `${annualCount}명`, icon: Calendar, iconColor: 'text-blue-500' },
      { label: '경조사', value: `${condolenceCount}명`, icon: Heart, iconColor: 'text-pink-500' },
      { label: '연간 연차 사용률', value: `${usageRate}%`, icon: TrendingUp, iconColor: 'text-green-500' },
    ];
  }, [usageData, grantData, requestData]);

  // ===== 탭 옵션 (카드 아래에 표시됨) =====
  const tabs: TabOption[] = useMemo(() => [
    { value: 'usage', label: MAIN_TAB_LABELS.usage, mobileLabel: '사용', count: usageData.length, color: 'blue' },
    { value: 'grant', label: MAIN_TAB_LABELS.grant, mobileLabel: '부여', count: grantData.length, color: 'green' },
    { value: 'request', label: MAIN_TAB_LABELS.request, mobileLabel: '신청', count: requestData.length, color: 'purple' },
  ], [usageData.length, grantData.length, requestData.length]);

  // ===== 테이블 컬럼 (탭별) =====
  const tableColumns: TableColumn[] = useMemo(() => {
    if (mainTab === 'usage') {
      // 휴가 사용현황: 번호|부서|직책|이름|직급|입사일|기본|부여|사용|잔액
      return [
        { key: 'no', label: '번호', className: 'w-[60px] text-center' },
        { key: 'department', label: '부서', sortable: true, copyable: true },
        { key: 'position', label: '직책', sortable: true, copyable: true },
        { key: 'name', label: '이름', sortable: true, copyable: true },
        { key: 'rank', label: '직급', sortable: true, copyable: true },
        { key: 'hireDate', label: '입사일', sortable: true, copyable: true },
        { key: 'base', label: '기본', className: 'text-center', sortable: true, copyable: true },
        { key: 'granted', label: '부여', className: 'text-center', sortable: true, copyable: true },
        { key: 'used', label: '사용', className: 'text-center', sortable: true, copyable: true },
        { key: 'remaining', label: '잔여', className: 'text-center', sortable: true, copyable: true },
      ];
    } else if (mainTab === 'grant') {
      // 휴가 부여현황: 번호|부서|직책|이름|직급|유형|부여일|부여휴가일수|사유
      return [
        { key: 'no', label: '번호', className: 'w-[60px] text-center' },
        { key: 'department', label: '부서', sortable: true, copyable: true },
        { key: 'position', label: '직책', sortable: true, copyable: true },
        { key: 'name', label: '이름', sortable: true, copyable: true },
        { key: 'rank', label: '직급', sortable: true, copyable: true },
        { key: 'type', label: '유형', sortable: true, copyable: true },
        { key: 'grantDate', label: '부여일', sortable: true, copyable: true },
        { key: 'grantDays', label: '부여휴가일수', className: 'text-center', sortable: true, copyable: true },
        { key: 'reason', label: '사유', sortable: true, copyable: true },
      ];
    } else {
      // 휴가 신청현황: 번호|부서|직책|이름|직급|휴가기간|휴가일수|상태|신청일
      return [
        { key: 'no', label: '번호', className: 'w-[60px] text-center' },
        { key: 'department', label: '부서', sortable: true, copyable: true },
        { key: 'position', label: '직책', sortable: true, copyable: true },
        { key: 'name', label: '이름', sortable: true, copyable: true },
        { key: 'rank', label: '직급', sortable: true, copyable: true },
        { key: 'period', label: '휴가기간', sortable: true, copyable: true },
        { key: 'days', label: '휴가일수', className: 'text-center', sortable: true, copyable: true },
        { key: 'status', label: '상태', className: 'text-center', sortable: true },
        { key: 'requestDate', label: '신청일', sortable: true, copyable: true },
      ];
    }
  }, [mainTab]);

  // ===== 테이블 행 렌더링 =====
  const renderTableRow = useCallback((
    item: any,
    index: number,
    globalIndex: number,
    handlers: { isSelected: boolean; onToggle: () => void; onRowClick?: () => void }
  ) => {
    const { isSelected, onToggle } = handlers;

    if (mainTab === 'usage') {
      const record = item as VacationUsageRecord;
      const hireDateStr = record.hireDate && record.hireDate !== '-' ? format(new Date(record.hireDate), 'yyyy-MM-dd') : '-';
      return (
        <TableRow key={record.id} className="hover:bg-muted/50">
          <TableCell className="text-center">
            <Checkbox checked={isSelected} onCheckedChange={onToggle} />
          </TableCell>
          <TableCell className="text-center">{globalIndex}</TableCell>
          <TableCell>{record.department}</TableCell>
          <TableCell>{record.position}</TableCell>
          <TableCell className="font-medium">{record.employeeName}</TableCell>
          <TableCell>{record.rank}</TableCell>
          <TableCell>{hireDateStr}</TableCell>
          <TableCell className="text-center">{record.baseVacation}</TableCell>
          <TableCell className="text-center">{record.grantedVacation}</TableCell>
          <TableCell className="text-center">{record.usedVacation}</TableCell>
          <TableCell className="text-center font-medium">{record.remainingVacation}</TableCell>
        </TableRow>
      );
    } else if (mainTab === 'grant') {
      const record = item as VacationGrantRecord;
      const grantDateStr = record.grantDate ? format(new Date(record.grantDate), 'yyyy-MM-dd') : '-';
      return (
        <TableRow key={record.id} className="hover:bg-muted/50">
          <TableCell className="text-center">
            <Checkbox checked={isSelected} onCheckedChange={onToggle} />
          </TableCell>
          <TableCell className="text-center">{globalIndex}</TableCell>
          <TableCell>{record.department}</TableCell>
          <TableCell>{record.position}</TableCell>
          <TableCell className="font-medium">{record.employeeName}</TableCell>
          <TableCell>{record.rank}</TableCell>
          <TableCell>
            <Badge variant="outline">{VACATION_TYPE_LABELS[record.vacationType]}</Badge>
          </TableCell>
          <TableCell>{grantDateStr}</TableCell>
          <TableCell className="text-center">{record.grantDays}일</TableCell>
          <TableCell className="text-muted-foreground">{record.reason || '-'}</TableCell>
        </TableRow>
      );
    } else {
      const record = item as VacationRequestRecord;
      const startDateStr = record.startDate ? format(new Date(record.startDate), 'yyyy-MM-dd') : '-';
      const endDateStr = record.endDate ? format(new Date(record.endDate), 'yyyy-MM-dd') : '-';
      const requestDateStr = record.requestDate ? format(new Date(record.requestDate), 'yyyy-MM-dd') : '-';
      return (
        <TableRow key={record.id} className="hover:bg-muted/50">
          <TableCell className="text-center">
            <Checkbox checked={isSelected} onCheckedChange={onToggle} />
          </TableCell>
          <TableCell className="text-center">{globalIndex}</TableCell>
          <TableCell>{record.department}</TableCell>
          <TableCell>{record.position}</TableCell>
          <TableCell className="font-medium">{record.employeeName}</TableCell>
          <TableCell>{record.rank}</TableCell>
          <TableCell>
            {startDateStr} ~ {endDateStr}
          </TableCell>
          <TableCell className="text-center">{record.vacationDays}일</TableCell>
          <TableCell className="text-center">
            <Badge className={REQUEST_STATUS_COLORS[record.status]}>
              {REQUEST_STATUS_LABELS[record.status]}
            </Badge>
          </TableCell>
          <TableCell>{requestDateStr}</TableCell>
        </TableRow>
      );
    }
  }, [mainTab]);

  // ===== 모바일 카드 렌더링 =====
  const renderMobileCard = useCallback((
    item: any,
    index: number,
    globalIndex: number,
    handlers: { isSelected: boolean; onToggle: () => void; onRowClick?: () => void }
  ) => {
    const { isSelected, onToggle } = handlers;
    if (mainTab === 'usage') {
      const record = item as VacationUsageRecord;
      return (
        <ListMobileCard
          id={record.id}
          title={record.employeeName}
          headerBadges={<Badge variant="outline">{record.department}</Badge>}
          isSelected={isSelected}
          onToggleSelection={onToggle}
          infoGrid={
            <div className="grid grid-cols-2 gap-3">
              <InfoField label="직급" value={record.rank} />
              <InfoField label="입사일" value={record.hireDate} />
              <InfoField label="기본" value={record.baseVacation} />
              <InfoField label="부여" value={record.grantedVacation} />
              <InfoField label="사용" value={record.usedVacation} />
              <InfoField label="잔여" value={record.remainingVacation} />
            </div>
          }
        />
      );
    } else if (mainTab === 'grant') {
      const record = item as VacationGrantRecord;
      return (
        <ListMobileCard
          id={record.id}
          title={record.employeeName}
          headerBadges={<Badge variant="outline">{VACATION_TYPE_LABELS[record.vacationType]}</Badge>}
          isSelected={isSelected}
          onToggleSelection={onToggle}
          infoGrid={
            <div className="grid grid-cols-2 gap-3">
              <InfoField label="부서" value={record.department} />
              <InfoField label="직급" value={record.rank} />
              <InfoField label="부여일" value={record.grantDate} />
              <InfoField label="일수" value={`${record.grantDays}일`} />
              {record.reason && <InfoField label="사유" value={record.reason} />}
            </div>
          }
        />
      );
    } else {
      const record = item as VacationRequestRecord;
      return (
        <ListMobileCard
          id={record.id}
          title={record.employeeName}
          headerBadges={
            <Badge className={REQUEST_STATUS_COLORS[record.status]}>
              {REQUEST_STATUS_LABELS[record.status]}
            </Badge>
          }
          isSelected={isSelected}
          onToggleSelection={onToggle}
          infoGrid={
            <div className="grid grid-cols-2 gap-3">
              <InfoField label="부서" value={record.department} />
              <InfoField label="직급" value={record.rank} />
              <InfoField label="기간" value={`${record.startDate} ~ ${record.endDate}`} />
              <InfoField label="일수" value={`${record.vacationDays}일`} />
              <InfoField label="신청일" value={record.requestDate} />
            </div>
          }
          actions={
            record.status === 'pending' && (
              <div className="flex gap-2">
                <Button variant="default" className="flex-1" onClick={() => handleApproveClick(new Set([record.id]))}>
                  <Check className="w-4 h-4 mr-2" /> 승인
                </Button>
                <Button variant="outline" className="flex-1" onClick={() => handleRejectClick(new Set([record.id]))}>
                  <X className="w-4 h-4 mr-2" /> 거절
                </Button>
              </div>
            )
          }
        />
      );
    }
  }, [mainTab, handleApproveClick, handleRejectClick]);

  // ===== 헤더 액션 (탭별 버튼들만 - 선택 액션은 selectionActions로 분리) =====
  const headerActions = useCallback(() => (
    <div className="flex items-center gap-2">
      {mainTab === 'grant' && (
        <Button onClick={() => setGrantDialogOpen(true)}>
          <Plus className="h-4 w-4 mr-2" />
          부여등록
        </Button>
      )}
      {mainTab === 'request' && (
        <Button onClick={() => setRequestDialogOpen(true)}>
          <Plus className="h-4 w-4 mr-2" />
          휴가신청
        </Button>
      )}
    </div>
  ), [mainTab]);

  // ===== filterConfig 기반 통합 필터 시스템 =====
  const filterConfig: FilterFieldConfig[] = useMemo(() => [
    {
      key: 'filter',
      label: '필터',
      type: 'single',
      options: FILTER_OPTIONS.filter(o => o.value !== 'all').map(o => ({
        value: o.value,
        label: o.label,
      })),
      allOptionLabel: '휴가 전체',
    },
    {
      key: 'sort',
      label: '정렬',
      type: 'single',
      options: SORT_OPTIONS.map(o => ({
        value: o.value,
        label: o.label,
      })),
    },
  ], []);

  const _filterValues: FilterValues = useMemo(() => ({
    filter: filterOption,
    sort: sortOption,
  }), [filterOption, sortOption]);

  const handleFilterChange = useCallback((filters: Record<string, string | string[]>) => {
    Object.entries(filters).forEach(([key, value]) => {
      switch (key) {
        case 'filter':
          setFilterOption(value as FilterOption);
          break;
        case 'sort':
          setSortOption(value as SortOption);
          break;
      }
    });
  }, []);

  const _handleFilterReset = useCallback(() => {
    setFilterOption('all');
    setSortOption('rank');
  }, []);

  // ===== UniversalListPage 설정 =====
  const vacationConfig: UniversalListConfig<any> = useMemo(() => ({
    title: '휴가관리',
    description: '직원들의 휴가 현황을 관리합니다',
    icon: Calendar,
    basePath: '/hr/vacation-management',

    idField: 'id',

    actions: {
      getList: async () => ({
        success: true,
        data: currentData,
        totalCount: currentData.length,
      }),
    },

    columns: tableColumns,

    // 신청현황 탭에서만 날짜 필터 표시 (사용현황/부여현황은 연간 데이터)
    dateRangeSelector: {
      enabled: mainTab === 'request',
      startDate,
      endDate,
      onStartDateChange: setStartDate,
      onEndDateChange: setEndDate,
    },

    tabs: tabs,
    defaultTab: mainTab,

    searchPlaceholder: '이름, 부서 검색...',

    itemsPerPage: itemsPerPage,

    clientSideFiltering: true,

    searchFilter: (item, searchValue) => {
      return (
        item.employeeName?.includes(searchValue) ||
        item.department?.includes(searchValue)
      );
    },

    // tabFilter 제거: 탭별로 다른 데이터를 사용하므로 원래 tabs.count 유지

    computeStats: () => statCards,

    filterConfig: filterConfig,

    headerActions: headerActions,

    selectionActions: ({ selectedItems: selected }) => {
      if (mainTab !== 'request') return null;
      return (
        <>
          <Button size="sm" variant="default" onClick={() => handleApproveClick(selected)}>
            <Check className="h-4 w-4 mr-2" />
            승인
          </Button>
          <Button size="sm" variant="destructive" onClick={() => handleRejectClick(selected)}>
            <X className="h-4 w-4 mr-2" />
            거절
          </Button>
        </>
      );
    },

    renderTableRow: renderTableRow,

    renderMobileCard: renderMobileCard,

    renderDialogs: (_params) => (
      <>
        {/* 휴가 부여 다이얼로그 */}
        <VacationGrantDialog
          open={grantDialogOpen}
          onOpenChange={setGrantDialogOpen}
          onSave={async (data) => {
            try {
              const result = await createLeaveGrant({
                userId: parseInt(data.employeeId, 10),
                grantType: data.vacationType as LeaveGrantType,
                grantDate: data.grantDate,
                grantDays: data.grantDays,
                reason: data.reason,
              });
              if (result.success) {
                invalidateDashboard('leave');
                await fetchGrantData();
                await fetchUsageData();
              } else {
                toast.error(`휴가 부여 실패: ${result.error}`);
                console.error('[VacationManagement] 휴가 부여 실패:', result.error);
              }
            } catch (error) {
              if (isNextRedirectError(error)) throw error;
              console.error('[VacationManagement] 휴가 부여 에러:', error);
              toast.error('휴가 부여 중 오류가 발생했습니다.');
            } finally {
              setGrantDialogOpen(false);
            }
          }}
        />

        {/* 휴가 신청 다이얼로그 */}
        <VacationRequestDialog
          open={requestDialogOpen}
          onOpenChange={setRequestDialogOpen}
          onSave={async (data) => {
            try {
              const result = await createLeave({
                userId: parseInt(data.employeeId, 10),
                leaveType: data.leaveType,
                startDate: data.startDate,
                endDate: data.endDate,
                days: data.vacationDays,
              });
              if (result.success) {
                invalidateDashboard('leave');
                await fetchLeaveRequests();
                await fetchUsageData();
              } else {
                toast.error(`휴가 신청 실패: ${result.error}`);
                console.error('[VacationManagement] 휴가 신청 실패:', result.error);
              }
            } catch (error) {
              if (isNextRedirectError(error)) throw error;
              console.error('[VacationManagement] 휴가 신청 에러:', error);
              toast.error('휴가 신청 중 오류가 발생했습니다.');
            } finally {
              setRequestDialogOpen(false);
            }
          }}
        />

        {/* 승인 확인 다이얼로그 */}
        <ConfirmDialog
          open={approveDialogOpen}
          onOpenChange={setApproveDialogOpen}
          title="휴가 승인"
          description={`정말 ${selectedItems.size}건을 승인하시겠습니까?`}
          confirmText="승인"
          variant="success"
          onConfirm={handleApproveConfirm}
        />

        {/* 거절 확인 다이얼로그 */}
        <ConfirmDialog
          open={rejectDialogOpen}
          onOpenChange={setRejectDialogOpen}
          title="휴가 거절"
          description={`정말 ${selectedItems.size}건을 거절하시겠습니까?`}
          confirmText="거절"
          variant="destructive"
          onConfirm={handleRejectConfirm}
        />
      </>
    ),
  }), [
    currentData,
    tableColumns,
    tabs,
    mainTab,
    itemsPerPage,
    statCards,
    filterConfig,
    headerActions,
    handleApproveClick,
    handleRejectClick,
    renderTableRow,
    renderMobileCard,
    grantDialogOpen,
    requestDialogOpen,
    approveDialogOpen,
    rejectDialogOpen,
    selectedItems.size,
    handleApproveConfirm,
    handleRejectConfirm,
    fetchGrantData,
    fetchUsageData,
    fetchLeaveRequests,
  ]);

  return (
    <UniversalListPage<any>
      config={vacationConfig}
      initialData={currentData}
      initialTotalCount={currentData.length}
      onTabChange={handleMainTabChange}
      onSearchChange={setSearchQuery}
      onFilterChange={handleFilterChange}
      externalIsLoading={isLoading}
    />
  );
}