import { useState, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { Outlet, NavLink, useNavigate, useLocation } from 'react-router-dom';
import {
  LogOut, ChevronLeft, ChevronRight,
  Shield, Bell, Search, Clock, Lock,
  Download, FileSpreadsheet, Printer,
} from 'lucide-react';
import { useAuth } from '@/app/auth/AuthContext';
import { getRoleColorHex } from '@shared/constants/userRoles';
import { NotificationBanner, NotificationPopup, type SystemNotice } from '@shared/components/common/NotificationBanner';
import { useSettingsStore } from '@stores/settingsStore';
import { useMenuStore, getMenuLabel, type MenuConfigItem } from '@stores/menuStore';
import { resolveIcon } from '@/app/iconRegistry';

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


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

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

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);
  const { getTopLevelEntries, getChildren } = useMenuStore();

  // getPageLabel: DB 메뉴에서 현재 라우트 페이지명 (DB labels 기반)
  const getPageLabel = (pathname: string): string => {
    const allItems = useMenuStore.getState().items.filter((i) => i.menuType === 'ITEM' && i.urlPath);
    const item = allItems.find((n) => pathname.startsWith(n.urlPath!));
    return item ? getMenuLabel(item, language) : '';
  };

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

  // 인쇄
  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 ? getRoleColorHex(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" style={{ color: roleColor ?? undefined }}>{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>
        )}

        {/* 네비게이션 — DB menu_config 기반 동적 렌더링 + RBAC 필터 */}
        <nav className="flex-1 overflow-y-auto py-2 px-2 space-y-0.5">
          {getTopLevelEntries().map((entry) => {
            if (entry.menuType === 'GROUP') {
              return (
                <GroupMenu
                  key={entry.menuCd}
                  group={entry}
                  children={getChildren(entry.menuCd)}
                  collapsed={collapsed}
                  hasAccess={hasAccess}
                  openGroups={openGroups}
                  toggleGroup={toggleGroup}
                  location={location}
                  language={language}
                />
              );
            }
            // 일반 ITEM
            if (!entry.urlPath || !hasAccess(entry.urlPath)) return null;
            const Icon = resolveIcon(entry.icon);
            return (
              <NavLink
                key={entry.menuCd}
                to={entry.urlPath}
                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'
                  }`
                }
              >
                {Icon && <Icon className="w-4 h-4 shrink-0" />}
                {!collapsed && <span className="whitespace-nowrap overflow-hidden text-ellipsis">{getMenuLabel(entry, language)}</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 aria-label={t('layout.searchPlaceholder')}
                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 type="button" aria-label={t('layout.notifications', { defaultValue: '알림' })} 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 bg-white/[0.04]" style={{ color: roleColor }}>
                    {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
              aria-label="페이지 내 검색"
              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-400 hover:bg-blue-300 text-on-bright 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"
        >
          <Outlet />
        </main>
      </div>

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

/* ─── 그룹 메뉴 서브 컴포넌트 (DB 기반) ─── */
function GroupMenu({
  group,
  children,
  collapsed,
  hasAccess,
  openGroups,
  toggleGroup,
  location,
  language,
}: {
  group: MenuConfigItem;
  children: MenuConfigItem[];
  collapsed: boolean;
  hasAccess: (path: string) => boolean;
  openGroups: Set<string>;
  toggleGroup: (name: string) => void;
  location: { pathname: string };
  language: string;
}) {
  const navItems = children.filter((c) => c.menuType === 'ITEM' && c.urlPath);
  const accessibleItems = navItems.filter((c) => hasAccess(c.urlPath!));
  if (accessibleItems.length === 0) return null;

  const GroupIcon = resolveIcon(group.icon);
  const isAnyActive = accessibleItems.some((c) => location.pathname.startsWith(c.urlPath!));
  const isOpen = openGroups.has(group.menuCd) || isAnyActive;

  return (
    <div>
      <button
        type="button"
        onClick={() => toggleGroup(group.menuCd)}
        className={`flex items-center gap-2.5 px-3 py-2 rounded-lg text-[12px] font-medium w-full transition-colors ${
          isOpen ? 'text-foreground bg-surface-overlay' : 'text-hint hover:bg-surface-overlay hover:text-label'
        }`}
      >
        {GroupIcon && <GroupIcon className="w-4 h-4 shrink-0" />}
        {!collapsed && (
          <>
            <span className="flex-1 text-left whitespace-nowrap overflow-hidden text-ellipsis">
              {getMenuLabel(group, language)}
            </span>
            <ChevronRight className={`w-3 h-3 shrink-0 transition-transform ${isOpen ? 'rotate-90' : ''}`} />
          </>
        )}
      </button>
      {isOpen && (
        <div className={`mt-0.5 space-y-0.5 ${collapsed ? '' : 'ml-3 pl-2 border-l border-border'}`}>
          {children.map((child) => {
            if (child.menuType === 'DIVIDER') {
              if (collapsed) return null;
              return (
                <div key={child.menuCd} className="pt-2 pb-0.5 px-2.5">
                  <span className="text-[8px] font-bold text-hint uppercase tracking-wider">{child.dividerLabel}</span>
                </div>
              );
            }
            if (!child.urlPath || !hasAccess(child.urlPath)) return null;
            const ChildIcon = resolveIcon(child.icon);
            return (
              <NavLink
                key={child.menuCd}
                to={child.urlPath}
                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'
                  }`
                }
              >
                {ChildIcon && <ChildIcon className="w-3.5 h-3.5 shrink-0" />}
                {!collapsed && (
                  <span className="whitespace-nowrap overflow-hidden text-ellipsis">{getMenuLabel(child, language)}</span>
                )}
              </NavLink>
            );
          })}
        </div>
      )}
    </div>
  );
}
