'use client';

import { useState, useCallback, useEffect, useRef, useMemo } from 'react';
import { toast } from 'sonner';
import {
  Plus,
  RefreshCw,
  Copy,
  Download,
  FileText,
  Info,
  Loader2,
  Wallet,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Input } from '@/components/ui/input';
import { Card, CardContent } from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
import { Separator } from '@/components/ui/separator';
import { PageLayout } from '@/components/organisms/PageLayout';
import { PageHeader } from '@/components/organisms/PageHeader';
import { MobileCard, InfoField } from '@/components/organisms/MobileCard';
import { CurrencyInput } from '@/components/ui/currency-input';
import {
  TableRow,
  TableCell,
} from '@/components/ui/table';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import {
  IntegratedListTemplateV2,
  type TableColumn,
} from '@/components/templates/IntegratedListTemplateV2';
import { useColumnSettings } from '@/hooks/useColumnSettings';
import { ColumnSettingsPopover } from '@/components/molecules/ColumnSettingsPopover';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import {
  getPayrolls,
  getPayroll,
  getPayrollSummary,
  bulkGeneratePayrolls,
  copyFromPrevious,
  exportPayrollExcel,
  createJournalEntries,
  getPayrollSettings,
  updatePayrollSettings,
} from './actions';
import type {
  PayrollRecord,
  PayrollDetail,
  PayrollSummary,
  PayrollSettings,
  PayrollStatus,
} from './types';
import {
  PAYROLL_STATUS_LABELS,
  PAYROLL_STATUS_COLORS,
  formatCurrency,
} from './types';
import { SalaryRegistrationDialog } from './SalaryRegistrationDialog';
import { SalaryDetailDialog } from './SalaryDetailDialog';

// ===== 상수 =====
const ITEMS_PER_PAGE = 20;
const currentYear = new Date().getFullYear();
const YEAR_OPTIONS = Array.from({ length: 3 }, (_, i) => currentYear - 1 + i);
const MONTH_OPTIONS = Array.from({ length: 12 }, (_, i) => i + 1);

// ===== 테이블 컬럼 정의 =====
const TABLE_COLUMNS: TableColumn[] = [
  { key: 'no', label: '번호', className: 'text-center w-[60px]' },
  { key: 'userName', label: '사원', copyable: true },
  { key: 'department', label: '부서' },
  { key: 'baseSalary', label: '기본급', className: 'text-right' },
  { key: 'allowancesTotal', label: '수당', className: 'text-right' },
  { key: 'grossSalary', label: '총지급액', className: 'text-right' },
  { key: 'totalDeductions', label: '공제액', className: 'text-right' },
  { key: 'netSalary', label: '실수령액', className: 'text-right' },
  { key: 'status', label: '상태', className: 'text-center w-[80px]' },
  { key: 'actions', label: '작업', className: 'text-center w-[80px]' },
];

export function SalaryManagement() {
  // ===== 연월 =====
  const [year, setYear] = useState(currentYear);
  const [month, setMonth] = useState(new Date().getMonth() + 1);

  // ===== 탭 =====
  const [activeTab, setActiveTab] = useState<'list' | 'settings'>('list');

  // ===== 컬럼 설정 =====
  const {
    visibleColumns,
    allColumnsWithVisibility,
    columnWidths,
    setColumnWidth,
    toggleColumnVisibility,
    resetSettings,
    hasHiddenColumns,
  } = useColumnSettings({
    pageId: 'salary-management',
    columns: TABLE_COLUMNS,
    alwaysVisibleKeys: ['no', 'userName', 'actions'],
  });

  // ===== 목록 상태 =====
  const [records, setRecords] = useState<PayrollRecord[]>([]);
  const [summary, setSummary] = useState<PayrollSummary | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [currentPage, setCurrentPage] = useState(1);
  const [totalPages, setTotalPages] = useState(1);
  const [totalCount, setTotalCount] = useState(0);
  const isInitialLoad = useRef(true);

  // ===== 필터 =====
  const [searchQuery, setSearchQuery] = useState('');
  const [filterDepartment, setFilterDepartment] = useState('all');
  const [filterStatus, setFilterStatus] = useState('all');

  // ===== 선택 (string ID) =====
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());

  // ===== 다이얼로그 =====
  const [registrationOpen, setRegistrationOpen] = useState(false);
  const [detailOpen, setDetailOpen] = useState(false);
  const [selectedDetail, setSelectedDetail] = useState<PayrollDetail | null>(null);
  const [helpOpen, setHelpOpen] = useState(false);
  const [journalHelpOpen, setJournalHelpOpen] = useState(false);

  // ===== 확인 다이얼로그 =====
  const [bulkGenerateConfirm, setBulkGenerateConfirm] = useState(false);
  const [copyPrevConfirm, setCopyPrevConfirm] = useState(false);
  const [journalConfirm, setJournalConfirm] = useState(false);

  // ===== 로딩 상태 =====
  const [isActionLoading, setIsActionLoading] = useState(false);

  // ===== 설정 상태 =====
  const [settings, setSettings] = useState<PayrollSettings | null>(null);
  const [settingsLoading, setSettingsLoading] = useState(false);

  // ========================================
  // 데이터 로드
  // ========================================
  const loadData = useCallback(async () => {
    if (isInitialLoad.current) setIsLoading(true);
    try {
      const [listResult, summaryResult] = await Promise.all([
        getPayrolls({
          year,
          month,
          search: searchQuery || undefined,
          status: filterStatus !== 'all' ? filterStatus : undefined,
          page: currentPage,
          per_page: ITEMS_PER_PAGE,
        }),
        getPayrollSummary({ year, month }),
      ]);

      if (listResult.success && listResult.data) {
        setRecords(listResult.data);
        setTotalCount(listResult.pagination?.total || 0);
        setTotalPages(listResult.pagination?.lastPage || 1);
      } else {
        setRecords([]);
        setTotalCount(0);
        setTotalPages(1);
      }

      if (summaryResult.success && summaryResult.data) {
        setSummary(summaryResult.data);
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      console.error('loadData error:', error);
    } finally {
      setIsLoading(false);
      isInitialLoad.current = false;
    }
  }, [year, month, searchQuery, filterStatus, currentPage]);

  useEffect(() => {
    loadData();
  }, [loadData]);

  // ===== 설정 로드 =====
  const loadSettings = useCallback(async () => {
    setSettingsLoading(true);
    try {
      const result = await getPayrollSettings();
      if (result.success && result.data) {
        setSettings(result.data);
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      console.error('loadSettings error:', error);
    } finally {
      setSettingsLoading(false);
    }
  }, []);

  useEffect(() => {
    if (activeTab === 'settings' && !settings) {
      loadSettings();
    }
  }, [activeTab, settings, loadSettings]);

  // ========================================
  // 체크박스 (string ID)
  // ========================================
  const toggleSelection = useCallback((id: string) => {
    setSelectedIds(prev => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  }, []);

  const toggleSelectAll = useCallback(() => {
    if (selectedIds.size === records.length && records.length > 0) {
      setSelectedIds(new Set());
    } else {
      setSelectedIds(new Set(records.map(r => String(r.id))));
    }
  }, [selectedIds.size, records]);

  // ========================================
  // 상세 보기
  // ========================================
  const handleViewDetail = useCallback(async (record: PayrollRecord) => {
    setIsActionLoading(true);
    try {
      const result = await getPayroll(record.id);
      if (result.success && result.data) {
        setSelectedDetail(result.data);
        setDetailOpen(true);
      } else {
        toast.error(result.error || '급여 상세를 불러오는데 실패했습니다.');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error('급여 상세를 불러오는데 실패했습니다.');
    } finally {
      setIsActionLoading(false);
    }
  }, []);

  // ========================================
  // 일괄 생성
  // ========================================
  const handleBulkGenerate = useCallback(async () => {
    setBulkGenerateConfirm(false);
    setIsActionLoading(true);
    try {
      const result = await bulkGeneratePayrolls({ year, month });
      if (result.success) {
        toast.success(`${result.count || 0}건의 급여가 일괄 생성되었습니다.`);
        await loadData();
      } else {
        toast.error(result.error || '일괄 생성에 실패했습니다.');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error('일괄 생성에 실패했습니다.');
    } finally {
      setIsActionLoading(false);
    }
  }, [year, month, loadData]);

  // ========================================
  // 전월 복사
  // ========================================
  const handleCopyPrevious = useCallback(async () => {
    setCopyPrevConfirm(false);
    setIsActionLoading(true);
    try {
      const result = await copyFromPrevious({ year, month });
      if (result.success) {
        toast.success(`${result.count || 0}건의 급여가 복사되었습니다.`);
        await loadData();
      } else {
        toast.error(result.error || '전월 복사에 실패했습니다.');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error('전월 복사에 실패했습니다.');
    } finally {
      setIsActionLoading(false);
    }
  }, [year, month, loadData]);

  // ========================================
  // 엑셀 다운로드
  // ========================================
  const handleExcelDownload = useCallback(async () => {
    setIsActionLoading(true);
    try {
      const result = await exportPayrollExcel({ year, month, status: filterStatus });
      if (result.success && result.data) {
        const url = URL.createObjectURL(result.data);
        const a = document.createElement('a');
        a.href = url;
        a.download = result.filename || `급여_${year}_${month}.xlsx`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
        toast.success('엑셀 다운로드 완료');
      } else {
        toast.error(result.error || '엑셀 다운로드에 실패했습니다.');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error('엑셀 다운로드에 실패했습니다.');
    } finally {
      setIsActionLoading(false);
    }
  }, [year, month, filterStatus]);

  // ========================================
  // 전표 생성
  // ========================================
  const handleJournalEntry = useCallback(async () => {
    setJournalConfirm(false);
    setIsActionLoading(true);
    try {
      const result = await createJournalEntries({ year, month });
      if (result.success) {
        toast.success(`${year}년 ${month}월 급여 전표가 생성되었습니다.`);
      } else {
        toast.error(result.error || '전표 생성에 실패했습니다.');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error('전표 생성에 실패했습니다.');
    } finally {
      setIsActionLoading(false);
    }
  }, [year, month]);

  // ========================================
  // 급여 등록 콜백
  // ========================================
  const handleCreatePayroll = useCallback(async () => {
    setRegistrationOpen(false);
    await loadData();
  }, [loadData]);

  // ========================================
  // 급여 상세 저장/삭제 후 콜백
  // ========================================
  const handleDetailSaved = useCallback(async () => {
    setDetailOpen(false);
    setSelectedDetail(null);
    await loadData();
  }, [loadData]);

  // ========================================
  // 설정 저장
  // ========================================
  const handleSaveSettings = useCallback(async () => {
    if (!settings) return;
    setIsActionLoading(true);
    try {
      const result = await updatePayrollSettings({
        health_insurance_rate: settings.healthInsuranceRate,
        long_term_care_rate: settings.longTermCareRate,
        pension_rate: settings.pensionRate,
        employment_insurance_rate: settings.employmentInsuranceRate,
        pension_max_salary: settings.pensionMaxSalary,
        pension_min_salary: settings.pensionMinSalary,
        pay_day: settings.payDay,
        auto_calculate: settings.autoCalculate,
      });
      if (result.success) {
        toast.success('급여 설정이 저장되었습니다.');
        if (result.data) setSettings(result.data);
      } else {
        toast.error(result.error || '설정 저장에 실패했습니다.');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error('설정 저장에 실패했습니다.');
    } finally {
      setIsActionLoading(false);
    }
  }, [settings]);

  // ========================================
  // 부서 목록 (데이터에서 추출)
  // ========================================
  const departments = useMemo(() =>
    Array.from(new Set(records.map(r => r.department).filter(d => d && d !== '-'))),
    [records]
  );

  // ========================================
  // 통계 카드
  // ========================================
  const statCardsData = useMemo(() => [
    { label: '총 지급액', value: formatCurrency(summary?.totalGross || 0), icon: Wallet, iconColor: 'text-blue-600' },
    { label: '총 공제액', value: formatCurrency(summary?.totalDeductions || 0), icon: Wallet, iconColor: 'text-red-600' },
    { label: '실수령 총액', value: formatCurrency(summary?.totalNet || 0), icon: Wallet, iconColor: 'text-green-600' },
    { label: '대상 인원', value: `${summary?.totalCount || 0}명`, icon: Wallet, iconColor: 'text-purple-600' },
    { label: '미확정', value: `${summary?.draftCount || 0}건`, icon: Wallet, iconColor: 'text-orange-600' },
  ], [summary]);

  // ========================================
  // 상태 필터 변경 핸들러
  // ========================================
  const handleStatusTabChange = useCallback((value: string) => {
    setFilterStatus(value);
    setCurrentPage(1);
  }, []);

  // ========================================
  // 테이블 행 렌더링
  // ========================================
  const renderTableRow = useCallback((item: PayrollRecord, _index: number, globalIndex: number) => (
    <TableRow
      key={item.id}
      className="cursor-pointer hover:bg-muted/50"
      onClick={() => handleViewDetail(item)}
    >
      <TableCell className="text-center" onClick={(e) => e.stopPropagation()}>
        <Checkbox
          checked={selectedIds.has(String(item.id))}
          onCheckedChange={() => toggleSelection(String(item.id))}
        />
      </TableCell>
      <TableCell className="text-center">{globalIndex}</TableCell>
      <TableCell className="font-medium">{item.userName}</TableCell>
      <TableCell>{item.department || '-'}</TableCell>
      <TableCell className="text-right font-mono">{formatCurrency(item.baseSalary)}</TableCell>
      <TableCell className="text-right font-mono">{formatCurrency(item.allowancesTotal)}</TableCell>
      <TableCell className="text-right font-mono font-medium">{formatCurrency(item.grossSalary)}</TableCell>
      <TableCell className="text-right font-mono text-red-600">{formatCurrency(item.totalDeductions)}</TableCell>
      <TableCell className="text-right font-mono font-medium text-green-600">{formatCurrency(item.netSalary)}</TableCell>
      <TableCell className="text-center">
        <Badge className={PAYROLL_STATUS_COLORS[item.status]}>
          {PAYROLL_STATUS_LABELS[item.status]}
        </Badge>
      </TableCell>
      <TableCell className="text-center" onClick={(e) => e.stopPropagation()}>
        <Button variant="ghost" size="sm" className="h-7 text-xs" onClick={() => handleViewDetail(item)}>
          상세
        </Button>
      </TableCell>
    </TableRow>
  ), [selectedIds, toggleSelection, handleViewDetail]);

  // ========================================
  // 모바일 카드 렌더링
  // ========================================
  const renderMobileCard = useCallback((item: PayrollRecord, _index: number, _globalIndex: number, isSelected: boolean, onToggle: () => void) => (
    <MobileCard
      title={item.userName}
      subtitle={item.department || '-'}
      isSelected={isSelected}
      onToggleSelection={onToggle}
      onClick={() => handleViewDetail(item)}
      headerBadges={
        <Badge className={PAYROLL_STATUS_COLORS[item.status]}>
          {PAYROLL_STATUS_LABELS[item.status]}
        </Badge>
      }
      infoGrid={
        <div className="grid grid-cols-2 gap-3">
          <InfoField label="기본급" value={formatCurrency(item.baseSalary)} />
          <InfoField label="수당" value={formatCurrency(item.allowancesTotal)} />
          <InfoField label="총지급액" value={formatCurrency(item.grossSalary)} valueClassName="font-semibold" />
          <InfoField label="공제액" value={formatCurrency(item.totalDeductions)} valueClassName="text-red-600" />
          <InfoField label="실수령액" value={formatCurrency(item.netSalary)} valueClassName="text-green-600 font-semibold" />
        </div>
      }
    />
  ), [handleViewDetail]);

  // ========================================
  // 공통: 탭 버튼 (목록/설정)
  // ========================================
  const renderTopTabs = () => (
    <div className="flex gap-4 border-b w-full">
      <button
        className={`pb-2 text-sm font-medium border-b-2 transition-colors ${
          activeTab === 'list'
            ? 'border-primary text-primary'
            : 'border-transparent text-muted-foreground hover:text-foreground'
        }`}
        onClick={() => setActiveTab('list')}
      >
        급여 목록
      </button>
      <button
        className={`pb-2 text-sm font-medium border-b-2 transition-colors ${
          activeTab === 'settings'
            ? 'border-primary text-primary'
            : 'border-transparent text-muted-foreground hover:text-foreground'
        }`}
        onClick={() => setActiveTab('settings')}
      >
        급여 설정
      </button>
    </div>
  );

  // ========================================
  // 공통: 다이얼로그들
  // ========================================
  const renderDialogs = () => (
    <>
      <SalaryRegistrationDialog
        open={registrationOpen}
        onOpenChange={setRegistrationOpen}
        defaultYear={year}
        defaultMonth={month}
        onSaved={handleCreatePayroll}
      />
      <SalaryDetailDialog
        open={detailOpen}
        onOpenChange={setDetailOpen}
        payrollDetail={selectedDetail}
        onSaved={handleDetailSaved}
      />
      <PayrollHelpModal open={helpOpen} onOpenChange={setHelpOpen} />
      <JournalEntryHelpModal open={journalHelpOpen} onOpenChange={setJournalHelpOpen} />

      {/* 확인 팝업: 일괄 생성 */}
      <AlertDialog open={bulkGenerateConfirm} onOpenChange={setBulkGenerateConfirm}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>일괄 생성</AlertDialogTitle>
            <AlertDialogDescription>
              {year}년 {month}월 재직 사원 전체의 급여를 일괄 생성하시겠습니까?
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>취소</AlertDialogCancel>
            <AlertDialogAction onClick={handleBulkGenerate}>확인</AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {/* 확인 팝업: 전월 복사 */}
      <AlertDialog open={copyPrevConfirm} onOpenChange={setCopyPrevConfirm}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>전월 복사</AlertDialogTitle>
            <AlertDialogDescription>
              {year}년 {month}월 급여를 전월 데이터로 복사 등록하시겠습니까?
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>취소</AlertDialogCancel>
            <AlertDialogAction onClick={handleCopyPrevious}>확인</AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {/* 확인 팝업: 전표 생성 */}
      <AlertDialog open={journalConfirm} onOpenChange={setJournalConfirm}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>전표 생성</AlertDialogTitle>
            <AlertDialogDescription>
              {year}년 {month}월 급여 데이터로 일반전표를 생성하시겠습니까?
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>취소</AlertDialogCancel>
            <AlertDialogAction onClick={handleJournalEntry}>확인</AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </>
  );

  // ========================================
  // 헤더 액션 버튼 (액션 버튼들)
  // ========================================
  const headerActions = (
    <>
      <Button size="sm" variant="outline" className="bg-amber-600 text-white hover:bg-amber-700 border-0" onClick={() => setBulkGenerateConfirm(true)} disabled={isActionLoading}>
        <RefreshCw className="h-4 w-4 mr-1" />
        일괄 생성
      </Button>
      <Button size="sm" variant="outline" className="bg-orange-500 text-white hover:bg-orange-600 border-0" onClick={() => setCopyPrevConfirm(true)} disabled={isActionLoading}>
        <Copy className="h-4 w-4 mr-1" />
        전월 복사
      </Button>
      <Button size="sm" variant="outline" className="bg-purple-600 text-white hover:bg-purple-700 border-0" onClick={handleExcelDownload} disabled={isActionLoading}>
        <Download className="h-4 w-4 mr-1" />
        엑셀 다운로드
      </Button>
      <Button size="sm" variant="outline" className="bg-indigo-700 text-white hover:bg-indigo-800 border-0" onClick={() => setJournalConfirm(true)} disabled={isActionLoading}>
        <FileText className="h-4 w-4 mr-1" />
        전표 생성
      </Button>
    </>
  );

  // ========================================
  // 테이블 내 필터 (부서 + 상태)
  // ========================================
  const tableHeaderActionsNode = (
    <div className="flex items-center gap-2">
      <Select value={filterDepartment} onValueChange={setFilterDepartment}>
        <SelectTrigger className="min-w-[120px] w-auto">
          <SelectValue placeholder="전체 부서" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="all">전체 부서</SelectItem>
          {departments.map(d => (
            <SelectItem key={d} value={d}>{d}</SelectItem>
          ))}
        </SelectContent>
      </Select>
      <Select value={filterStatus} onValueChange={handleStatusTabChange}>
        <SelectTrigger className="min-w-[120px] w-auto">
          <SelectValue placeholder="전체 상태" />
        </SelectTrigger>
        <SelectContent>
          <SelectItem value="all">전체 상태</SelectItem>
          <SelectItem value="draft">작성중</SelectItem>
          <SelectItem value="confirmed">확정</SelectItem>
          <SelectItem value="paid">지급완료</SelectItem>
        </SelectContent>
      </Select>
    </div>
  );

  // ========================================
  // 부서 필터 적용된 데이터
  // ========================================
  const filteredRecords = useMemo(() =>
    filterDepartment === 'all'
      ? records
      : records.filter(r => r.department === filterDepartment),
    [records, filterDepartment]
  );

  // ========================================
  // 렌더링: 설정 탭
  // ========================================
  if (activeTab === 'settings') {
    return (
      <PageLayout>
        <PageHeader
          icon={Wallet}
          title="급여관리"
          description="사원 급여를 등록하고 관리합니다"
        />
        <div className="mobile-actions-grid xl:flex xl:items-center xl:gap-2 xl:shrink-0">
          {headerActions}
          <Button onClick={() => setRegistrationOpen(true)}>
            <Plus className="h-4 w-4 mr-2" />
            급여 등록
          </Button>
        </div>
        {renderTopTabs()}
        <SettingsTab
          settings={settings}
          setSettings={setSettings}
          isLoading={settingsLoading}
          onSave={handleSaveSettings}
          isSaving={isActionLoading}
        />
        {renderDialogs()}
      </PageLayout>
    );
  }

  // ========================================
  // 렌더링: 목록 탭 (IntegratedListTemplateV2)
  // ========================================
  return (
    <>
      <IntegratedListTemplateV2<PayrollRecord>
        title={
          <span className="flex items-center gap-1">
            급여관리
            <Button variant="ghost" size="icon" className="h-7 w-7" onClick={() => setHelpOpen(true)}>
              <Info className="h-4 w-4 text-blue-500" />
            </Button>
            <Button variant="ghost" size="icon" className="h-7 w-7" onClick={() => setJournalHelpOpen(true)}>
              <FileText className="h-4 w-4 text-indigo-500" />
            </Button>
          </span>
        }
        description="사원 급여를 등록하고 관리합니다"
        icon={Wallet}
        dateRangeSelector={{
          enabled: true,
          hideDateInputs: true,
          showPresets: false,
          extraActions: (
            <div className="flex items-center gap-2 flex-wrap">
              <Select value={String(year)} onValueChange={(v) => { setYear(Number(v)); setCurrentPage(1); }}>
                <SelectTrigger className="w-[100px] h-9">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {YEAR_OPTIONS.map(y => (
                    <SelectItem key={y} value={String(y)}>{y}년</SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <Select value={String(month)} onValueChange={(v) => { setMonth(Number(v)); setCurrentPage(1); }}>
                <SelectTrigger className="w-[80px] h-9">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {MONTH_OPTIONS.map(m => (
                    <SelectItem key={m} value={String(m)}>{m}월</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          ),
        }}
        headerActions={headerActions}
        createButton={{
          label: '급여 등록',
          onClick: () => setRegistrationOpen(true),
        }}
        searchValue={searchQuery}
        onSearchChange={setSearchQuery}
        searchPlaceholder="사원 이름, 부서 검색..."
        tabsContent={renderTopTabs()}
        stats={statCardsData}
        tableHeaderActions={tableHeaderActionsNode}
        tableColumns={visibleColumns}
        data={filteredRecords}
        selectedItems={selectedIds}
        onToggleSelection={toggleSelection}
        onToggleSelectAll={toggleSelectAll}
        getItemId={(item) => String(item.id)}
        renderTableRow={renderTableRow}
        renderMobileCard={renderMobileCard}
        pagination={{
          currentPage,
          totalPages,
          totalItems: totalCount,
          itemsPerPage: ITEMS_PER_PAGE,
          onPageChange: setCurrentPage,
        }}
        isLoading={isLoading}
        columnSettings={{
          columnWidths,
          onColumnResize: setColumnWidth,
          settingsPopover: (
            <ColumnSettingsPopover
              columns={allColumnsWithVisibility}
              onToggle={toggleColumnVisibility}
              onReset={resetSettings}
              hasHiddenColumns={hasHiddenColumns}
            />
          ),
        }}
      />
      {renderDialogs()}
    </>
  );
}

// ================================================================
// 급여 설정 탭
// ================================================================
function SettingsTab({
  settings,
  setSettings,
  isLoading,
  onSave,
  isSaving,
}: {
  settings: PayrollSettings | null;
  setSettings: (s: PayrollSettings) => void;
  isLoading: boolean;
  onSave: () => void;
  isSaving: boolean;
}) {
  if (isLoading || !settings) {
    return (
      <Card>
        <CardContent className="p-8 text-center">
          <Loader2 className="h-6 w-6 animate-spin mx-auto text-muted-foreground" />
        </CardContent>
      </Card>
    );
  }

  const update = (field: keyof PayrollSettings, value: number | boolean) => {
    setSettings({ ...settings, [field]: value });
  };

  return (
    <Card>
      <CardContent className="p-6 space-y-6">
        <div>
          <h3 className="text-lg font-semibold">급여 설정</h3>
          <p className="text-sm text-muted-foreground">4대보험 요율 및 급여 지급일 설정</p>
        </div>

        <Separator />

        {/* 4대보험 요율 */}
        <div>
          <h4 className="font-medium mb-3">4대보험 요율 (%)</h4>
          <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
            <div>
              <label className="text-sm text-muted-foreground block mb-1">건강보험료율</label>
              <Input
                type="number"
                step="0.001"
                value={settings.healthInsuranceRate}
                onChange={(e) => update('healthInsuranceRate', parseFloat(e.target.value) || 0)}
              />
            </div>
            <div>
              <label className="text-sm text-muted-foreground block mb-1">장기요양보험료율 (건강보험의 %)</label>
              <Input
                type="number"
                step="0.0001"
                value={settings.longTermCareRate}
                onChange={(e) => update('longTermCareRate', parseFloat(e.target.value) || 0)}
              />
            </div>
            <div>
              <label className="text-sm text-muted-foreground block mb-1">국민연금 요율</label>
              <Input
                type="number"
                step="0.001"
                value={settings.pensionRate}
                onChange={(e) => update('pensionRate', parseFloat(e.target.value) || 0)}
              />
            </div>
            <div>
              <label className="text-sm text-muted-foreground block mb-1">고용보험 요율</label>
              <Input
                type="number"
                step="0.001"
                value={settings.employmentInsuranceRate}
                onChange={(e) => update('employmentInsuranceRate', parseFloat(e.target.value) || 0)}
              />
            </div>
          </div>
        </div>

        {/* 국민연금 기준소득월액 */}
        <div>
          <h4 className="font-medium mb-3">국민연금 기준소득월액</h4>
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
            <div>
              <label className="text-sm text-muted-foreground block mb-1">상한액 (원)</label>
              <CurrencyInput
                value={settings.pensionMaxSalary}
                onChange={(v) => update('pensionMaxSalary', v ?? 0)}
              />
            </div>
            <div>
              <label className="text-sm text-muted-foreground block mb-1">하한액 (원)</label>
              <CurrencyInput
                value={settings.pensionMinSalary}
                onChange={(v) => update('pensionMinSalary', v ?? 0)}
              />
            </div>
          </div>
        </div>

        {/* 기타 설정 */}
        <div>
          <h4 className="font-medium mb-3">기타 설정</h4>
          <div className="flex flex-wrap items-end gap-6">
            <div className="w-[200px]">
              <label className="text-sm text-muted-foreground block mb-1">급여 지급일</label>
              <Input
                type="number"
                min={1}
                max={31}
                value={settings.payDay}
                onChange={(e) => update('payDay', parseInt(e.target.value) || 25)}
              />
            </div>
            <label className="flex items-center gap-2 pb-2 cursor-pointer">
              <Checkbox
                checked={settings.autoCalculate}
                onCheckedChange={(checked) => update('autoCalculate', !!checked)}
              />
              <span className="text-sm">급여 등록 시 자동 계산</span>
            </label>
          </div>
        </div>

        <Separator />

        <div className="flex justify-end">
          <Button onClick={onSave} disabled={isSaving}>
            {isSaving && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
            설정 저장
          </Button>
        </div>
      </CardContent>
    </Card>
  );
}

// ================================================================
// 급여계산 도움말 모달
// ================================================================
function PayrollHelpModal({ open, onOpenChange }: { open: boolean; onOpenChange: (v: boolean) => void }) {
  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="w-[calc(100vw-2rem)] sm:max-w-[700px] max-h-[80vh] overflow-y-auto overflow-x-hidden">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <Info className="h-5 w-5 text-blue-500" />
            급여계산 도움말
          </DialogTitle>
        </DialogHeader>
        <div className="space-y-4 text-sm min-w-0">
          <div>
            <h4 className="font-semibold mb-1">1. 급여계산의 전체 흐름</h4>
            <p className="text-muted-foreground">기본급 + 수당 + 총 지급액 → 공제(4대보험+세금) → 실수령액</p>
          </div>

          <Separator />

          <div>
            <h4 className="font-semibold mb-2">2. 지급 항목 (회사가 주는 금액)</h4>
            <div className="space-y-3">
              <div className="border rounded-md p-2.5">
                <p className="font-medium">기본급</p>
                <p className="text-muted-foreground text-xs mt-0.5">근로계약서에 정해진 월 기본 급여입니다.</p>
              </div>
              <div className="border rounded-md p-2.5">
                <p className="font-medium">고정연장근로수당</p>
                <p className="text-muted-foreground text-xs mt-0.5">매달 고정으로 지급되는 연장근무 수당입니다. 포괄 연봉제 대비에 결재한 금액을 지급합니다.</p>
              </div>
              <div className="border rounded-md p-2.5">
                <p className="font-medium">식대(비과세)</p>
                <p className="text-muted-foreground text-xs mt-0.5">월 20만원의 비과세한도가 있는 식비 지원금입니다. 총 지급액에는 포함되지만, 보험료 계산에서는 제외됩니다.</p>
              </div>
              <div className="border rounded-md p-2.5">
                <p className="font-medium">추가 수당</p>
                <p className="text-muted-foreground text-xs mt-0.5">교통비, 직책수당 등 추가로 지급되는 수당입니다. 이 금액은 과세 대상에 포함됩니다.</p>
              </div>
            </div>
            <p className="text-muted-foreground mt-2 text-xs">
              <strong>총 지급액</strong> = 기본급 + 고정연장근로수당 + 식대 + 추가 수당 합계<br />
              <strong>과세표준</strong> = 총 지급액 - 식대(비과세)
            </p>
          </div>

          <Separator />

          <div>
            <h4 className="font-semibold mb-2">3. 공제 항목 — 4대보험</h4>
            <p className="text-muted-foreground mb-2 text-xs">기본급을 기준으로 보험료가 계산됩니다 (원 단위 반올림).</p>
            <div className="space-y-3">
              <div className="border rounded-md p-2.5">
                <p className="font-medium">국민연금</p>
                <p className="text-muted-foreground text-xs mt-0.5">기본급 × 4.500% (상/하한액 적용)</p>
              </div>
              <div className="border rounded-md p-2.5">
                <p className="font-medium">건강보험</p>
                <p className="text-muted-foreground text-xs mt-0.5">기본급 × 3.545%</p>
              </div>
              <div className="border rounded-md p-2.5">
                <p className="font-medium">장기요양보험</p>
                <p className="text-muted-foreground text-xs mt-0.5"><strong>건강보험료</strong> × 0.9082% (건강보험에서 별도 계산)</p>
              </div>
              <div className="border rounded-md p-2.5">
                <p className="font-medium">고용보험</p>
                <p className="text-muted-foreground text-xs mt-0.5">기본급 × 0.900%</p>
              </div>
            </div>
          </div>

          <Separator />

          <div>
            <h4 className="font-semibold mb-2">4. 공제 항목 — 세금 (근로소득세 + 지방소득세)</h4>
            <p className="text-muted-foreground text-xs">
              <strong>근로소득세</strong>: 과세표준과 공제대상 가족수에 따라 결정됩니다.<br />
              국세청이 고시하는 간이세액표를 토대로 합니다 (기본 = 본인 1명).<br />
              기본 세금비교 = 간이세액 × 100%, 다른 비율(80, 120%)도 지정이 가능합니다.<br /><br />
              <strong>지방소득세</strong>: 근로소득세의 10%를 추가로 납부합니다.
            </p>
          </div>
        </div>
        <div className="flex justify-end mt-4">
          <Button variant="outline" onClick={() => onOpenChange(false)}>닫기</Button>
        </div>
      </DialogContent>
    </Dialog>
  );
}

// ================================================================
// 전표 생성 도움말 모달
// ================================================================
function JournalEntryHelpModal({ open, onOpenChange }: { open: boolean; onOpenChange: (v: boolean) => void }) {
  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="w-[calc(100vw-2rem)] sm:max-w-[700px] max-h-[80vh] overflow-y-auto overflow-x-hidden">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <FileText className="h-5 w-5 text-indigo-600" />
            급여 전표 생성 도움말
          </DialogTitle>
        </DialogHeader>
        <div className="space-y-4 text-sm min-w-0">
          <div>
            <h4 className="font-semibold mb-1">1. 전표 생성이란?</h4>
            <p className="text-muted-foreground text-xs">
              선택한 연/월의 급여 데이터를 합산하여 일반전표(분개)를 자동으로 생성합니다.
              생성된 전표는 <strong>회계관리 &gt; 일반전표입력</strong> 메뉴에서 확인할 수 있습니다.
            </p>
          </div>

          <Separator />

          <div>
            <h4 className="font-semibold mb-2">2. 분개 구조</h4>
            <div className="space-y-2">
              <div className="border rounded-md p-2.5 bg-blue-50">
                <div className="flex items-center gap-2 mb-1">
                  <Badge variant="outline" className="bg-blue-100">차변</Badge>
                  <span className="font-medium text-xs">801 급여</span>
                </div>
                <p className="text-xs text-muted-foreground">거래처: 임직원 / 적요: N월분 급여</p>
              </div>
              {[
                { account: '207 예수금', partner: '건강보험연금', desc: '국민연금' },
                { account: '207 예수금', partner: '건강보험건강', desc: '건강보험' },
                { account: '207 예수금', partner: '건강보험건강', desc: '장기요양보험' },
                { account: '207 예수금', partner: '건강보험고용', desc: '고용보험' },
                { account: '207 예수금', partner: '감사세무사', desc: 'N월분 근로소득세' },
                { account: '207 예수금', partner: '감사구청', desc: 'N월분 지방소득세' },
                { account: '205 미지급비용', partner: '임직원', desc: 'N월분 급여' },
              ].map((row, i) => (
                <div key={i} className="border rounded-md p-2.5">
                  <div className="flex items-center gap-2 mb-1">
                    <Badge variant="outline" className="bg-red-50">대변</Badge>
                    <span className="font-medium text-xs">{row.account}</span>
                  </div>
                  <p className="text-xs text-muted-foreground">거래처: {row.partner} / 적요: {row.desc}</p>
                </div>
              ))}
            </div>
          </div>

          <Separator />

          <div>
            <h4 className="font-semibold mb-1">3. 전표일자 및 번호</h4>
            <ul className="text-muted-foreground space-y-1 list-disc list-inside">
              <li>전표일자: 선택한 월의 말일 (예: 2월 → 2월 28일)</li>
              <li>전표번호: JE-YYYYMMDD-NNN 형식으로 자동 채번</li>
            </ul>
          </div>

          <Separator />

          <div>
            <h4 className="font-semibold mb-1">4. 주의사항</h4>
            <div className="space-y-2">
              <p className="bg-yellow-50 border border-yellow-200 rounded p-2 text-yellow-800">
                동일 월에 중복 생성 불가 — 이미 생성된 전표가 있으면 전표번호와 함께 안내됩니다.
              </p>
              <p className="bg-blue-50 border border-blue-200 rounded p-2 text-blue-800">
                공제금액이 0원인 항목은 분개 행에서 자동 제외됩니다.
              </p>
              <p className="bg-green-50 border border-green-200 rounded p-2 text-green-800">
                차변 = 대변 균형이 자동 검증됩니다.
              </p>
            </div>
          </div>

          <div>
            <h4 className="font-semibold mb-1">5. 전표 수정/삭제</h4>
            <p className="text-muted-foreground">
              생성된 전표를 수정하거나 삭제하려면 <strong>회계관리 &gt; 일반전표입력</strong> 메뉴에서 해당 전표를 찾아 처리하세요. 전표 삭제 후 이 페이지에서 다시 생성할 수 있습니다.
            </p>
          </div>
        </div>
        <div className="flex justify-end mt-4">
          <Button variant="outline" onClick={() => onOpenChange(false)}>닫기</Button>
        </div>
      </DialogContent>
    </Dialog>
  );
}
