import { useState, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { Outlet, NavLink, useNavigate, useLocation } from 'react-router-dom';
import {
  LayoutDashboard, Map, List, Ship, Anchor, Radar,
  FileText, Settings, LogOut, ChevronLeft, ChevronRight,
  Shield, Bell, Search, Fingerprint, Clock, Lock, Database, Megaphone, Layers,
  Download, FileSpreadsheet, Printer, Wifi, Brain, Activity,
  ChevronsLeft, ChevronsRight,
  Navigation, Users, EyeOff, BarChart3, Globe,
  Smartphone, Monitor, Send, Cpu, MessageSquare,
} from 'lucide-react';
import { useAuth, type UserRole } from '@/app/auth/AuthContext';
import { NotificationBanner, NotificationPopup, type SystemNotice } from '@shared/components/common/NotificationBanner';
import { useSettingsStore } from '@stores/settingsStore';

/*
 * SFR-01 반영 사항:
 * - RBAC 기반 메뉴 접근 제어 (역할별 허용 메뉴만 표시)
 * - 세션 타임아웃 잔여 시간 표시
 * - 로그인 사용자 정보·역할·인증방식 표시
 * - 로그아웃 시 감사 로그 기록
 *
 * SFR-02 공통기능:
 * - 모든 페이지 오른쪽 상단: 페이지 검색, 파일다운로드, 엑셀 내보내기, 인쇄
 * - 모든 페이지 하단: 페이지네이션
 */

const ROLE_COLORS: Record<UserRole, string> = {
  ADMIN: 'text-red-400',
  OPERATOR: 'text-blue-400',
  ANALYST: 'text-purple-400',
  FIELD: 'text-green-400',
  VIEWER: 'text-yellow-400',
};

const AUTH_METHOD_LABELS: Record<string, string> = {
  password: 'ID/PW',
  gpki: 'GPKI',
  sso: 'SSO',
};

interface NavItem { to: string; icon: React.ElementType; labelKey: string; }
interface NavGroup { groupKey: string; icon: React.ElementType; items: NavItem[]; }
type NavEntry = NavItem | NavGroup;

const isGroup = (entry: NavEntry): entry is NavGroup => 'groupKey' in entry;

const NAV_ENTRIES: NavEntry[] = [
  // ── 상황판·감시 ──
  { to: '/dashboard', icon: LayoutDashboard, labelKey: 'nav.dashboard' },
  { to: '/monitoring', icon: Activity, labelKey: 'nav.monitoring' },
  { to: '/events', icon: Radar, labelKey: 'nav.eventList' },
  { to: '/map-control', icon: Map, labelKey: 'nav.riskMap' },
  // ── 위험도·단속 ──
  { to: '/risk-map', icon: Layers, labelKey: 'nav.riskMap' },
  { to: '/enforcement-plan', icon: Shield, labelKey: 'nav.enforcementPlan' },
  // ── 탐지 ──
  { to: '/dark-vessel', icon: EyeOff, labelKey: 'nav.darkVessel' },
  { to: '/gear-detection', icon: Anchor, labelKey: 'nav.gearDetection' },
  { to: '/china-fishing', icon: Ship, labelKey: 'nav.chinaFishing' },
  // ── 이력·통계 ──
  { to: '/enforcement-history', icon: FileText, labelKey: 'nav.enforcementHistory' },
  { to: '/event-list', icon: List, labelKey: 'nav.eventList' },
  { to: '/statistics', icon: BarChart3, labelKey: 'nav.statistics' },
  { to: '/reports', icon: FileText, labelKey: 'nav.reports' },
  // ── 함정용 (그룹) ──
  {
    groupKey: 'group.fieldOps', icon: Ship,
    items: [
      { to: '/patrol-route', icon: Navigation, labelKey: 'nav.patrolRoute' },
      { to: '/fleet-optimization', icon: Users, labelKey: 'nav.fleetOptimization' },
      { to: '/ai-alert', icon: Send, labelKey: 'nav.aiAlert' },
      { to: '/mobile-service', icon: Smartphone, labelKey: 'nav.mobileService' },
      { to: '/ship-agent', icon: Monitor, labelKey: 'nav.shipAgent' },
    ],
  },
  // ── 관리자 (그룹) ──
  {
    groupKey: 'group.admin', icon: Settings,
    items: [
      { to: '/ai-model', icon: Brain, labelKey: 'nav.aiModel' },
      { to: '/mlops', icon: Cpu, labelKey: 'nav.mlops' },
      { to: '/ai-assistant', icon: MessageSquare, labelKey: 'nav.aiAssistant' },
      { to: '/external-service', icon: Globe, labelKey: 'nav.externalService' },
      { to: '/data-hub', icon: Wifi, labelKey: 'nav.dataHub' },
      { to: '/system-config', icon: Database, labelKey: 'nav.systemConfig' },
      { to: '/notices', icon: Megaphone, labelKey: 'nav.notices' },
      { to: '/admin', icon: Settings, labelKey: 'nav.admin' },
      { to: '/access-control', icon: Fingerprint, labelKey: 'nav.accessControl' },
    ],
  },
];

// getPageLabel용 flat 목록
const NAV_ITEMS = NAV_ENTRIES.flatMap(e => isGroup(e) ? e.items : [e]);

function formatRemaining(seconds: number) {
  const m = Math.floor(seconds / 60);
  const s = seconds % 60;
  return `${m}:${String(s).padStart(2, '0')}`;
}

// ─── 공통 페이지네이션 (간소형) ─────────────
function PagePagination({ page, totalPages, onPageChange }: {
  page: number; totalPages: number; onPageChange: (p: number) => void;
}) {
  if (totalPages <= 1) return null;
  const range: number[] = [];
  const maxVis = 5;
  let s = Math.max(0, page - Math.floor(maxVis / 2));
  const e = Math.min(totalPages - 1, s + maxVis - 1);
  if (e - s < maxVis - 1) s = Math.max(0, e - maxVis + 1);
  for (let i = s; i <= e; i++) range.push(i);

  const btnCls = "p-1 rounded text-hint hover:text-heading hover:bg-surface-overlay disabled:opacity-30 disabled:cursor-not-allowed transition-colors";

  return (
    <div className="flex items-center justify-center gap-1">
      <button onClick={() => onPageChange(0)} disabled={page === 0} className={btnCls}><ChevronsLeft className="w-3.5 h-3.5" /></button>
      <button onClick={() => onPageChange(page - 1)} disabled={page === 0} className={btnCls}><ChevronLeft className="w-3.5 h-3.5" /></button>
      {range.map((p) => (
        <button
          key={p}
          onClick={() => onPageChange(p)}
          className={`min-w-[22px] h-5 px-1 rounded text-[10px] font-medium transition-colors ${
            p === page ? 'bg-blue-600 text-heading' : 'text-muted-foreground hover:text-heading hover:bg-surface-overlay'
          }`}
        >{p + 1}</button>
      ))}
      <button onClick={() => onPageChange(page + 1)} disabled={page >= totalPages - 1} className={btnCls}><ChevronRight className="w-3.5 h-3.5" /></button>
      <button onClick={() => onPageChange(totalPages - 1)} disabled={page >= totalPages - 1} className={btnCls}><ChevronsRight className="w-3.5 h-3.5" /></button>
      <span className="text-[9px] text-hint ml-2">{page + 1} / {totalPages}</span>
    </div>
  );
}

export function MainLayout() {
  const { t } = useTranslation('common');
  const { theme, toggleTheme, language, toggleLanguage } = useSettingsStore();
  const [collapsed, setCollapsed] = useState(false);
  const navigate = useNavigate();
  const location = useLocation();
  const { user, logout, hasAccess, sessionRemaining } = useAuth();
  const contentRef = useRef<HTMLDivElement>(null);

  // getPageLabel: 현재 라우트에서 페이지명 가져오기 (i18n)
  const getPageLabel = (pathname: string): string => {
    const item = NAV_ITEMS.find((n) => pathname.startsWith(n.to));
    return item ? t(item.labelKey) : '';
  };

  // 공통 검색
  const [pageSearch, setPageSearch] = useState('');

  // 공통 스크롤 페이징 (페이지 단위 스크롤)
  const [scrollPage, setScrollPage] = useState(0);
  const scrollPageSize = 800; // px per page

  const handleScrollPageChange = (p: number) => {
    setScrollPage(p);
    if (contentRef.current) {
      contentRef.current.scrollTo({ top: p * scrollPageSize, behavior: 'smooth' });
    }
  };

  // 스크롤 이벤트로 현재 페이지 추적
  const handleScroll = () => {
    if (contentRef.current) {
      const { scrollTop, scrollHeight, clientHeight } = contentRef.current;
      const totalScrollPages = Math.max(1, Math.ceil((scrollHeight - clientHeight) / scrollPageSize) + 1);
      const currentPage = Math.min(Math.floor(scrollTop / scrollPageSize), totalScrollPages - 1);
      setScrollPage(currentPage);
    }
  };

  const getTotalScrollPages = () => {
    if (!contentRef.current) return 1;
    const { scrollHeight, clientHeight } = contentRef.current;
    return Math.max(1, Math.ceil((scrollHeight - clientHeight) / scrollPageSize) + 1);
  };

  // 인쇄
  const handlePrint = () => {
    const el = contentRef.current;
    if (!el) { window.print(); return; }
    const win = window.open('', '_blank');
    if (!win) return;
    win.document.write(`<html><head><title>${getPageLabel(location.pathname)} - ${t('layout.print')}</title>
      <style>body{font-family:'Pretendard',sans-serif;color:#1e293b;padding:20px}
      table{width:100%;border-collapse:collapse;font-size:11px}
      th,td{border:1px solid #cbd5e1;padding:6px 8px;text-align:left}
      th{background:#f1f5f9;font-weight:600}@media print{body{padding:0}}</style>
      </head><body>${el.innerHTML}</body></html>`);
    win.document.close();
    win.print();
  };

  // 엑셀(CSV) 내보내기 — 현재 화면 테이블 자동 추출
  const handleExcelExport = () => {
    const el = contentRef.current;
    if (!el) return;
    const tables = el.querySelectorAll('table');
    if (tables.length === 0) { alert(t('layout.noExportTable')); return; }
    const table = tables[0];
    const rows: string[] = [];
    table.querySelectorAll('tr').forEach((tr) => {
      const cells: string[] = [];
      tr.querySelectorAll('th, td').forEach((td) => {
        cells.push(`"${(td.textContent || '').replace(/"/g, '""').trim()}"`);
      });
      rows.push(cells.join(','));
    });
    const csv = '\uFEFF' + rows.join('\r\n');
    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${getPageLabel(location.pathname) || 'export'}_${new Date().toISOString().slice(0, 10)}.csv`;
    a.click();
    URL.revokeObjectURL(url);
  };

  // 파일 다운로드 (현재 페이지 HTML)
  const handleDownload = () => {
    const el = contentRef.current;
    if (!el) return;
    const html = `<html><head><meta charset="utf-8"><title>${getPageLabel(location.pathname)}</title></head><body>${el.innerHTML}</body></html>`;
    const blob = new Blob([html], { type: 'text/html;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${getPageLabel(location.pathname) || 'page'}_${new Date().toISOString().slice(0, 10)}.html`;
    a.click();
    URL.revokeObjectURL(url);
  };

  // 그룹 메뉴 접기/펼치기 (다중 그룹 지원)
  const [openGroups, setOpenGroups] = useState<Set<string>>(new Set());
  const toggleGroup = (name: string) => setOpenGroups(prev => {
    const next = new Set(prev);
    next.has(name) ? next.delete(name) : next.add(name);
    return next;
  });

  // RBAC
  const roleColor = user ? ROLE_COLORS[user.role] : null;
  const isSessionWarning = sessionRemaining <= 5 * 60;

  // SFR-02: 공통알림 데이터
  const systemNotices: SystemNotice[] = [
    {
      id: 'N-001', type: 'urgent', display: 'banner', title: '서해 NLL 인근 경보 강화',
      message: '2026-04-03부터 서해 NLL 인근 해역에 대한 경계 경보가 강화되었습니다.',
      startDate: '2026-04-03', endDate: '2026-04-10', targetRoles: ['ADMIN', 'OPERATOR'], dismissible: true, pinned: true,
    },
    {
      id: 'N-002', type: 'maintenance', display: 'popup', title: '정기 시스템 점검 안내',
      message: '2026-04-05(토) 02:00~06:00 시스템 정기점검이 예정되어 있습니다. 점검 중 서비스 이용이 제한될 수 있습니다.',
      startDate: '2026-04-03', endDate: '2026-04-05', targetRoles: [], dismissible: true, pinned: false,
    },
    {
      id: 'N-003', type: 'info', display: 'banner', title: 'AI 탐지 모델 v2.3 업데이트',
      message: '다크베셀 탐지 정확도 89%→93% 개선. 환적 탐지 알고리즘 업데이트.',
      startDate: '2026-04-01', endDate: '2026-04-15', targetRoles: ['ADMIN', 'ANALYST'], dismissible: true, pinned: false,
    },
  ];

  const handleLogout = () => {
    logout();
    navigate('/login');
  };

  return (
    <div className="flex h-screen bg-background text-heading overflow-hidden">
      {/* 사이드바 */}
      <aside
        className={`flex flex-col border-r border-border bg-background transition-all duration-300 ${
          collapsed ? 'w-16' : 'w-56'
        }`}
      >
        {/* 로고 */}
        <div className="flex items-center gap-2.5 px-4 h-14 border-b border-border shrink-0">
          <div className="flex items-center justify-center w-8 h-8 rounded-lg bg-blue-600/20 border border-blue-500/30 shrink-0">
            <Shield className="w-4 h-4 text-blue-400" />
          </div>
          {!collapsed && (
            <div className="min-w-0">
              <div className="text-[11px] font-bold text-heading truncate">{t('layout.brandTitle')}</div>
              <div className="text-[8px] text-hint truncate">{t('layout.brandSub')}</div>
            </div>
          )}
        </div>

        {/* RBAC 역할 표시 */}
        {!collapsed && user && roleColor && (
          <div className="mx-2 mt-2 px-3 py-2 rounded-lg bg-surface-overlay border border-border">
            <div className="flex items-center gap-1.5">
              <Lock className="w-3 h-3 text-hint" />
              <span className={`text-[9px] font-bold whitespace-nowrap overflow-hidden text-ellipsis ${roleColor}`}>{t(`role.${user.role}`)}</span>
            </div>
            <div className="text-[8px] text-hint mt-0.5">
              {t('layout.auth')} {AUTH_METHOD_LABELS[user.authMethod] || user.authMethod}
            </div>
          </div>
        )}

        {/* 네비게이션 — RBAC 기반 필터링 + 그룹 메뉴 */}
        <nav className="flex-1 overflow-y-auto py-2 px-2 space-y-0.5">
          {NAV_ENTRIES.map((entry) => {
            if (isGroup(entry)) {
              // 그룹 내 RBAC 필터링
              const groupItems = entry.items.filter((item) => hasAccess(item.to));
              if (groupItems.length === 0) return null;
              const GroupIcon = entry.icon;
              const isAnyActive = groupItems.some((item) => location.pathname.startsWith(item.to));
              return (
                <div key={entry.groupKey}>
                  {/* 그룹 헤더 */}
                  <button
                    onClick={() => toggleGroup(entry.groupKey)}
                    className={`flex items-center gap-2.5 px-3 py-2 rounded-lg text-[12px] font-medium w-full transition-colors ${
                      isAnyActive || openGroups.has(entry.groupKey)
                        ? 'text-foreground bg-surface-overlay'
                        : 'text-hint hover:bg-surface-overlay hover:text-label'
                    }`}
                  >
                    <GroupIcon className="w-4 h-4 shrink-0" />
                    {!collapsed && (
                      <>
                        <span className="flex-1 text-left whitespace-nowrap overflow-hidden text-ellipsis">{t(entry.groupKey)}</span>
                        <ChevronRight className={`w-3 h-3 shrink-0 transition-transform ${openGroups.has(entry.groupKey) || isAnyActive ? 'rotate-90' : ''}`} />
                      </>
                    )}
                  </button>
                  {/* 그룹 하위 메뉴 */}
                  {(openGroups.has(entry.groupKey) || isAnyActive) && (
                    <div className={`mt-0.5 space-y-0.5 ${collapsed ? '' : 'ml-3 pl-2 border-l border-border'}`}>
                      {groupItems.map((item) => (
                        <NavLink
                          key={item.to}
                          to={item.to}
                          className={({ isActive }) =>
                            `flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-[11px] font-medium transition-colors ${
                              isActive
                                ? 'bg-blue-600/15 text-blue-400 border border-blue-500/20'
                                : 'text-muted-foreground hover:bg-surface-overlay hover:text-foreground border border-transparent'
                            }`
                          }
                        >
                          <item.icon className="w-3.5 h-3.5 shrink-0" />
                          {!collapsed && <span className="whitespace-nowrap overflow-hidden text-ellipsis">{t(item.labelKey)}</span>}
                        </NavLink>
                      ))}
                    </div>
                  )}
                </div>
              );
            }
            // 일반 메뉴 아이템
            if (!hasAccess(entry.to)) return null;
            return (
              <NavLink
                key={entry.to}
                to={entry.to}
                className={({ isActive }) =>
                  `flex items-center gap-2.5 px-3 py-2 rounded-lg text-[12px] font-medium transition-colors ${
                    isActive
                      ? 'bg-blue-600/15 text-blue-400 border border-blue-500/20'
                      : 'text-muted-foreground hover:bg-surface-overlay hover:text-foreground border border-transparent'
                  }`
                }
              >
                <entry.icon className="w-4 h-4 shrink-0" />
                {!collapsed && <span className="whitespace-nowrap overflow-hidden text-ellipsis">{t(entry.labelKey)}</span>}
              </NavLink>
            );
          })}
        </nav>

        {/* 세션 타임아웃 표시 */}
        {!collapsed && user && (
          <div className={`mx-2 mb-1 px-3 py-1.5 rounded-lg text-[9px] flex items-center gap-1.5 ${
            isSessionWarning
              ? 'bg-red-500/10 border border-red-500/20 text-red-400'
              : 'bg-surface-overlay border border-border text-hint'
          }`}>
            <Clock className="w-3 h-3" />
            <span className="whitespace-nowrap overflow-hidden text-ellipsis">{t('layout.sessionExpiring')} {formatRemaining(sessionRemaining)}</span>
            {isSessionWarning && <span className="ml-auto text-[8px] whitespace-nowrap animate-pulse">{t('layout.extendNeeded')}</span>}
          </div>
        )}

        {/* 사이드바 하단 */}
        <div className="border-t border-border p-2 space-y-1 shrink-0">
          <button
            onClick={handleLogout}
            className="flex items-center gap-2.5 px-3 py-2 rounded-lg text-[12px] text-hint hover:text-red-400 hover:bg-red-500/10 w-full transition-colors"
          >
            <LogOut className="w-4 h-4 shrink-0" />
            {!collapsed && <span className="whitespace-nowrap overflow-hidden text-ellipsis">{t('layout.logout')}</span>}
          </button>
          <button
            onClick={() => setCollapsed(!collapsed)}
            className="flex items-center justify-center w-full py-1.5 rounded-lg text-hint hover:text-muted-foreground hover:bg-surface-overlay transition-colors"
          >
            {collapsed ? <ChevronRight className="w-4 h-4" /> : <ChevronLeft className="w-4 h-4" />}
          </button>
        </div>
      </aside>

      {/* 메인 영역 */}
      <div className="flex-1 flex flex-col min-w-0">
        {/* 헤더 */}
        <header className="flex items-center justify-between h-12 px-4 border-b border-border bg-background/80 backdrop-blur-sm shrink-0">
          <div className="flex items-center gap-3">
            <div className="relative">
              <Search className="absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-hint" />
              <input
                type="text"
                placeholder={t('layout.searchPlaceholder')}
                className="w-56 bg-surface-overlay border border-border rounded-lg pl-8 pr-3 py-1.5 text-[11px] text-heading placeholder:text-hint focus:outline-none focus:border-blue-500/40"
              />
            </div>
          </div>
          <div className="flex items-center gap-2">
            {/* 경보 */}
            <div className="flex items-center gap-1.5 px-2 py-1 bg-red-500/10 border border-red-500/20 rounded-lg">
              <div className="w-1.5 h-1.5 rounded-full bg-red-500 animate-pulse" />
              <span className="text-[10px] text-red-400 font-bold whitespace-nowrap">{t('layout.alertCount', { count: 3 })}</span>
            </div>
            <button className="relative p-1.5 rounded-lg hover:bg-surface-overlay text-muted-foreground hover:text-heading transition-colors">
              <Bell className="w-4 h-4" />
              <span className="absolute top-0.5 right-0.5 w-2 h-2 bg-red-500 rounded-full" />
            </button>
            <div className="w-px h-5 bg-white/[0.06]" />
            {/* 언어 토글 */}
            <button
              onClick={toggleLanguage}
              className="px-2 py-1 rounded-lg text-[10px] font-bold bg-surface-overlay border border-border text-label hover:text-heading transition-colors whitespace-nowrap"
              title={language === 'ko' ? 'Switch to English' : '한국어로 전환'}
            >
              {language === 'ko' ? 'EN' : '한국어'}
            </button>
            {/* 테마 토글 */}
            <button
              onClick={toggleTheme}
              className="p-1.5 rounded-lg bg-surface-overlay border border-border text-label hover:text-heading transition-colors"
              title={theme === 'dark' ? 'Light mode' : 'Dark mode'}
            >
              {theme === 'dark' ? (
                <svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                  <path strokeLinecap="round" strokeLinejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
                </svg>
              ) : (
                <svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                  <path strokeLinecap="round" strokeLinejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
                </svg>
              )}
            </button>
            <div className="w-px h-5 bg-white/[0.06]" />
            {user && (
              <div className="flex items-center gap-2">
                <div className="w-6 h-6 rounded-full bg-blue-600/20 border border-blue-500/30 flex items-center justify-center">
                  <span className="text-[9px] font-bold text-blue-400">{user.name.charAt(0)}</span>
                </div>
                <div className="text-right">
                  <div className="text-[10px] font-medium text-heading">
                    {user.name}
                    <span className="text-hint ml-1">({user.rank})</span>
                  </div>
                  <div className="text-[8px] text-hint">{user.org}</div>
                </div>
                {roleColor && (
                  <span className={`text-[8px] font-bold px-1.5 py-0.5 rounded whitespace-nowrap ${roleColor} bg-white/[0.04]`}>
                    {user.role}
                  </span>
                )}
              </div>
            )}
          </div>
        </header>

        {/* SFR-02: 공통알림 배너 */}
        <NotificationBanner notices={systemNotices} userRole={user?.role} />

        {/* SFR-02: 공통 페이지 액션바 (검색, 다운로드, 엑셀, 인쇄) */}
        <div className="flex items-center justify-end gap-1.5 px-4 py-1.5 border-b border-border bg-background/60 shrink-0">
          {/* 왼쪽: 페이지명 */}
          <div className="mr-auto text-[9px] text-hint">{getPageLabel(location.pathname)}</div>

          {/* 검색 입력 + 검색 버튼 통합 */}
          <div className="relative flex items-center">
            <Search className="absolute left-2.5 top-1/2 -translate-y-1/2 w-3 h-3 text-hint pointer-events-none" />
            <input
              value={pageSearch}
              onChange={(e) => setPageSearch(e.target.value)}
              onKeyDown={(e) => {
                if (e.key === 'Enter' && pageSearch) {
                  (window as unknown as { find: (s: string) => boolean }).find?.(pageSearch);
                }
              }}
              placeholder={t('layout.pageSearch')}
              className="w-48 bg-surface-overlay border border-slate-700/50 rounded-l-md pl-7 pr-2 py-1 text-[10px] text-label placeholder:text-hint focus:outline-none focus:border-blue-500/50"
            />
            <button
              onClick={() => {
                if (pageSearch) {
                  (window as unknown as { find: (s: string) => boolean }).find?.(pageSearch);
                }
              }}
              className="flex items-center gap-1 px-2.5 py-1 rounded-r-md text-[9px] bg-blue-600 hover:bg-blue-500 text-heading font-medium border border-blue-600 transition-colors"
            >
              <Search className="w-3 h-3" />
              {t('action.search')}
            </button>
          </div>

          <button
            onClick={handleDownload}
            className="flex items-center gap-1 px-2 py-1 rounded-md text-[9px] text-hint hover:text-label hover:bg-surface-overlay transition-colors whitespace-nowrap"
            title={t('layout.fileDownload')}
          >
            <Download className="w-3 h-3" />
            {t('layout.download')}
          </button>
          <button
            onClick={handleExcelExport}
            className="flex items-center gap-1 px-2 py-1 rounded-md text-[9px] text-hint hover:text-label hover:bg-surface-overlay transition-colors whitespace-nowrap"
            title={t('layout.excelExport')}
          >
            <FileSpreadsheet className="w-3 h-3" />
            {t('layout.excel')}
          </button>
          <button
            onClick={handlePrint}
            className="flex items-center gap-1 px-2 py-1 rounded-md text-[9px] text-hint hover:text-label hover:bg-surface-overlay transition-colors whitespace-nowrap"
            title={t('layout.print')}
          >
            <Printer className="w-3 h-3" />
            {t('layout.print')}
          </button>
        </div>

        {/* 콘텐츠 */}
        <main
          ref={contentRef}
          className="flex-1 overflow-auto"
          onScroll={handleScroll}
        >
          <Outlet />
        </main>

        {/* SFR-02: 공통 페이지네이션 (하단) */}
        <div className="shrink-0 border-t border-border bg-background/60 px-4 py-1">
          <PagePagination
            page={scrollPage}
            totalPages={getTotalScrollPages()}
            onPageChange={handleScrollPageChange}
          />
        </div>
      </div>

      {/* SFR-02: 공통알림 팝업 */}
      <NotificationPopup notices={systemNotices} userRole={user?.role} />
    </div>
  );
}
