import { useEffect, useState } from 'react';
import { Link, Outlet, useRouterState } from '@tanstack/react-router';
import { Database, Gauge, GitMerge, Languages, Menu, Moon, Radio, Scale, Search, Sparkles, Sun, Swords, Table, TrendingUp, Trophy, Users } from 'lucide-react';
import { SearchPalette } from '@/components/SearchPalette';
import type { LucideIcon } from 'lucide-react';
import { useUiStore } from '@/stores/uiStore';
import { useLocaleStore } from '@/stores/localeStore';
import { useTournamentStore } from '@/stores/tournamentStore';
import { fmt, useFormat, useT, type Dict } from '@/lib/i18n';
import { cn } from '@/lib/cn';

interface NavItem { to: string; label: (t: Dict) => string; exact: boolean; icon: LucideIcon }

const NAV: NavItem[] = [
  { to: '/', label: (t) => t.nav.live, exact: true, icon: Radio },
  { to: '/groups', label: (t) => t.nav.groups, exact: false, icon: Table },
  { to: '/bracket', label: (t) => t.nav.bracket, exact: false, icon: GitMerge },
  { to: '/predict', label: (t) => t.nav.predict, exact: false, icon: TrendingUp },
  { to: '/scoreboard', label: (t) => t.nav.vsMarket, exact: false, icon: Scale },
  { to: '/methodology', label: (t) => t.nav.model, exact: false, icon: Gauge },
  { to: '/story', label: (t) => t.nav.story, exact: false, icon: Sparkles },
];

// Phones get four primary tabs + a "More" sheet (7 tabs were unusably cramped).
const MOBILE_PRIMARY: NavItem[] = NAV.slice(0, 4);
const MOBILE_MORE: NavItem[] = [
  ...NAV.slice(4),
  { to: '/teams', label: (t) => t.nav.teams, exact: false, icon: Users },
  { to: '/compare', label: (t) => t.nav.compare, exact: false, icon: Swords },
  { to: '/data', label: (t) => t.nav.data, exact: false, icon: Database },
];

function ConnectionStatus() {
  const t = useT();
  const status = useTournamentStore((s) => s.status);
  const source = useTournamentStore((s) => s.snapshot?.source);
  if (status === 'live') {
    return (
      <span
        title={source && source !== 'seed' ? t.common.liveVia.replace('{source}', source) : t.common.connected}
        className="inline-flex items-center gap-1.5 rounded-full border border-accent-deep/40 bg-accent-glow px-2 py-0.5 text-[11px] font-bold uppercase tracking-wide text-accent"
      >
        <span className="live-dot h-1.5 w-1.5 rounded-full bg-accent" />
        {t.common.liveNow}
      </span>
    );
  }
  return (
    <span
      title={status === 'connecting' ? t.common.connecting : t.common.offlineShowingSchedule}
      className="inline-flex items-center gap-1.5 rounded-full border border-line px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wide text-muted"
    >
      <span className="h-1.5 w-1.5 rounded-full bg-faint" />
      {status === 'connecting' ? '…' : t.common.offline}
    </span>
  );
}

function ThemeToggle() {
  const t = useT();
  const theme = useUiStore((s) => s.theme);
  const toggle = useUiStore((s) => s.toggleTheme);
  return (
    <button
      type="button"
      onClick={toggle}
      aria-label={theme === 'dark' ? t.common.switchToLightMode : t.common.switchToDarkMode}
      className="grid h-9 w-9 place-items-center rounded-md text-muted hover:bg-elevated hover:text-ink transition-colors"
    >
      {theme === 'dark' ? <Sun size={18} /> : <Moon size={18} />}
    </button>
  );
}

export function LanguageToggle() {
  const locale = useLocaleStore((s) => s.locale);
  const setLocale = useLocaleStore((s) => s.setLocale);
  return (
    <button
      type="button"
      onClick={() => setLocale(locale === 'en' ? 'de' : 'en')}
      aria-label={locale === 'en' ? 'Auf Deutsch umschalten' : 'Switch to English'}
      className="inline-flex h-9 items-center gap-1.5 rounded-md px-2 text-xs font-bold uppercase tracking-wide text-muted hover:bg-elevated hover:text-ink transition-colors"
    >
      <Languages size={16} />
      {locale === 'en' ? 'EN' : 'DE'}
    </button>
  );
}

/** Slim stale-data notice while the live connection is down. */
function OfflineBanner() {
  const { t, kickoffDay, kickoffTime } = useFormat();
  const status = useTournamentStore((s) => s.status);
  const updatedAt = useTournamentStore((s) => s.snapshot?.updatedAt);
  if (status !== 'offline' || !updatedAt) return null;
  return (
    <div className="border-b border-warning/30 bg-warning/10 px-4 py-1.5 text-center text-xs text-muted" role="status">
      {fmt(t.common.offlineBanner, { time: `${kickoffDay(updatedAt)} ${kickoffTime(updatedAt)}` })}
    </div>
  );
}

function MobileNav() {
  const t = useT();
  const [moreOpen, setMoreOpen] = useState(false);
  const pathname = useRouterState({ select: (s) => s.location.pathname });
  const moreActive = MOBILE_MORE.some((i) => pathname.startsWith(i.to));

  useEffect(() => setMoreOpen(false), [pathname]);

  return (
    <>
      {moreOpen && (
        <button
          type="button"
          aria-label={t.common.back}
          className="fixed inset-0 z-30 bg-black/40 sm:hidden"
          onClick={() => setMoreOpen(false)}
        />
      )}
      {moreOpen && (
        <div className="fixed inset-x-0 bottom-[52px] z-40 rounded-t-2xl border-t border-line bg-surface p-3 pb-4 shadow-2xl sm:hidden">
          <div className="grid grid-cols-2 gap-1.5">
            {MOBILE_MORE.map((item) => (
              <Link
                key={item.to}
                to={item.to}
                className={cn(
                  'flex min-h-11 items-center gap-2.5 rounded-lg px-3 py-2.5 text-sm font-medium text-muted hover:bg-elevated hover:text-ink',
                  '[&.active]:bg-accent-glow [&.active]:text-accent',
                )}
              >
                <item.icon size={17} />
                {item.label(t)}
              </Link>
            ))}
          </div>
          <div className="mt-2 flex items-center justify-end gap-1.5 border-t border-line pt-2">
            <LanguageToggle />
            <ThemeToggle />
          </div>
        </div>
      )}
      <nav className="fixed inset-x-0 bottom-0 z-40 flex border-t border-line bg-surface/95 backdrop-blur sm:hidden">
        {MOBILE_PRIMARY.map((item) => (
          <Link
            key={item.to}
            to={item.to}
            {...(item.exact ? { activeOptions: { exact: true } } : {})}
            className={cn(
              'flex min-h-[52px] flex-1 flex-col items-center justify-center gap-0.5 py-1.5 text-[11px] font-medium text-muted',
              '[&.active]:text-accent',
            )}
          >
            <item.icon size={18} />
            {item.label(t)}
          </Link>
        ))}
        <button
          type="button"
          onClick={() => setMoreOpen((v) => !v)}
          className={cn(
            'flex min-h-[52px] flex-1 flex-col items-center justify-center gap-0.5 py-1.5 text-[11px] font-medium',
            moreOpen || moreActive ? 'text-accent' : 'text-muted',
          )}
        >
          <Menu size={18} />
          {t.nav.more}
        </button>
      </nav>
    </>
  );
}

export function RootLayout() {
  const t = useT();
  const [searchOpen, setSearchOpen] = useState(false);

  useEffect(() => {
    useTournamentStore.getState().init();
  }, []);

  useEffect(() => {
    const onKey = (e: KeyboardEvent): void => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
        e.preventDefault();
        setSearchOpen((v) => !v);
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  return (
    <div className="flex min-h-full flex-col">
      <SearchPalette open={searchOpen} onClose={() => setSearchOpen(false)} />
      <header className="sticky top-0 z-30 border-b border-line bg-surface/85 backdrop-blur">
        <div className="mx-auto flex h-14 max-w-6xl items-center gap-4 px-4">
          <Link to="/" className="flex items-center gap-2 font-display text-lg font-extrabold tracking-tight text-ink">
            <span className="grid h-7 w-7 place-items-center rounded-md bg-gradient-to-b from-accent-soft to-accent text-accent-ink">
              <Trophy size={16} />
            </span>
            Cup<span className="text-accent">26</span>
          </Link>
          <nav className="hidden items-center gap-0.5 sm:flex">
            {NAV.map((item) => (
              <Link
                key={item.to}
                to={item.to}
                {...(item.exact ? { activeOptions: { exact: true } } : {})}
                className={cn(
                  'rounded-md px-3 py-1.5 text-sm font-medium text-muted transition-colors hover:bg-elevated hover:text-ink',
                  '[&.active]:bg-accent-glow [&.active]:text-accent',
                )}
              >
                {item.label(t)}
              </Link>
            ))}
          </nav>
          <div className="ml-auto flex items-center gap-1.5">
            <ConnectionStatus />
            <button
              type="button"
              onClick={() => setSearchOpen(true)}
              aria-label={t.search.title}
              className="grid h-9 w-9 place-items-center rounded-md text-muted hover:bg-elevated hover:text-ink transition-colors"
            >
              <Search size={17} />
            </button>
            <LanguageToggle />
            <ThemeToggle />
          </div>
        </div>
      </header>

      <OfflineBanner />

      <main className="mx-auto w-full max-w-6xl flex-1 px-4 py-6 pb-24 sm:pb-6">
        <Outlet />
      </main>

      <MobileNav />

      <footer className="border-t border-line py-6 pb-24 text-center text-xs text-faint sm:pb-6">
        <p>
          Cup26 · {t.footer.worldCup} · <Link to="/data" className="underline decoration-line underline-offset-2 hover:text-ink">{t.footer.allData}</Link> ·{' '}
          <Link to="/methodology" className="underline decoration-line underline-offset-2 hover:text-ink">{t.footer.howModelWorks}</Link> ·{' '}
          {t.footer.disclaimer}
        </p>
      </footer>
    </div>
  );
}
