import { lazy, Suspense, useEffect } from 'react';
import { BrowserRouter, Routes, Route, Navigate, useNavigate, useLocation, useNavigationType } from 'react-router-dom';
import { useGameStore } from './store/gameStore';
import { socket, emit } from './lib/socket';
import { trackEvent } from './lib/track';
import type { MyPlayer } from './types';
import GameList from './pages/GameList';
import Lobby from './pages/Lobby';
import GameTable from './pages/GameTable';
import Auth from './pages/Auth';
import History from './pages/History';
import Donate from './pages/Donate';

// Admin pulls in recharts — lazy-load it so players never download that chunk.
const AdminLayout = lazy(() => import('./pages/admin/AdminLayout'));
const AdminStats = lazy(() => import('./pages/admin/AdminStats'));

function AppInner() {
  const navigate = useNavigate();
  const location = useLocation();
  const navigationType = useNavigationType();
  const account = useGameStore((s) => s.account);
  const myPlayer = useGameStore((s) => s.myPlayer);
  const gameStatus = useGameStore((s) => s.gameStatus);
  const error = useGameStore((s) => s.error);
  const clearError = useGameStore((s) => s.clearError);

  // Reconnect into an in-progress game on every socket connect (after network drops).
  useEffect(() => {
    const doReconnect = () => {
      const saved = localStorage.getItem('bridzik_player');
      if (!saved) return;
      const player = JSON.parse(saved) as MyPlayer;
      emit.reconnectToGame(player.gid, player.token);
    };
    socket.on('connect', doReconnect);
    if (socket.connected) doReconnect();
    return () => { socket.off('connect', doReconnect); };
  }, []);

  // Single authoritative navigation:
  //  - not logged in            → /auth
  //  - logged in & in a game     → lobby/game
  //  - logged in, no game, on /auth (just logged in) → leave for the game list
  //  - logged in, no game, elsewhere → null (let the user navigate: list/history)
  const onGameRoute =
    location.pathname === '/auth' ||
    location.pathname.startsWith('/game') ||
    location.pathname.startsWith('/lobby');
  // /admin is a separate concern gated by its own token, not the player login.
  const onAdminRoute = location.pathname.startsWith('/admin');
  const targetRoute = onAdminRoute
    ? null
    : !account
      ? '/auth'
      : myPlayer
        ? gameStatus ? `/game/${gameStatus.gid}` : `/lobby/${myPlayer.gid}`
        : onGameRoute ? '/' : null;

  useEffect(() => {
    if (!targetRoute) return;
    navigate(targetRoute, { replace: true });
  }, [targetRoute, navigate]);

  // Auto-dismiss errors after 4 s
  useEffect(() => {
    if (!error) return;
    const t = setTimeout(clearError, 4000);
    return () => clearTimeout(t);
  }, [error, clearError]);

  // Fire-and-forget pageview beacon for self-hosted analytics; must never
  // affect the app (network errors are swallowed). Skip REPLACE navigations --
  // those are app-internal gate/index redirects (login gate, /admin index ->
  // stats), not a page the user actually navigated to, so they'd otherwise
  // inflate the count with one extra row per redirect hop. Skip /admin itself
  // too -- that's the dashboard viewing its own traffic, not player usage.
  // Skip /, /lobby, /game -- high-frequency in-game navigation with no
  // analytical value; the backend drops these anyway (api/stats.py _SKIPPED_PATHS).
  // The visitor's first touch (incl. landings on "/", which both skips would
  // otherwise swallow) is captured by trackLanding() in main.tsx instead.
  // Skip /auth too: it's only ever reached by a full page load (every in-app
  // redirect to it is REPLACE), so each /auth row would be a 1:1 duplicate of
  // the landing event fired by that same load.
  useEffect(() => {
    if (navigationType === 'REPLACE') return;
    if (location.pathname.startsWith('/admin')) return;
    if (
      location.pathname === '/' ||
      location.pathname === '/auth' ||
      location.pathname.startsWith('/lobby') ||
      location.pathname.startsWith('/game')
    ) {
      return;
    }
    trackEvent(location.pathname, document.referrer);
  }, [location.pathname, navigationType]);

  return (
    <>
      {error && (
        <div className="fixed top-4 left-1/2 -translate-x-1/2 z-50 bg-red-600 text-white px-4 py-2 rounded-lg shadow-lg text-sm max-w-xs text-center">
          {error}
        </div>
      )}
      <Suspense fallback={<p className="text-center text-green-dim pt-20 font-serif italic">Načítava sa…</p>}>
        <Routes>
          <Route path="/auth" element={<Auth />} />
          <Route path="/" element={<GameList />} />
          <Route path="/history" element={<History />} />
          <Route path="/donate" element={<Donate />} />
          <Route path="/lobby/:gid" element={<Lobby />} />
          <Route path="/game/:gid" element={<GameTable />} />
          <Route path="/admin" element={<AdminLayout />}>
            <Route index element={<Navigate to="stats" replace />} />
            <Route path="stats" element={<AdminStats />} />
          </Route>
          <Route path="*" element={<Navigate to="/" replace />} />
        </Routes>
      </Suspense>
    </>
  );
}

export default function App() {
  return (
    <BrowserRouter>
      <AppInner />
    </BrowserRouter>
  );
}
