import { lazy, Suspense, useEffect, useRef, useCallback } from "react";
import { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { SettingsProvider, useSettings } from "@/contexts/SettingsContext";
import { MusicProvider } from "@/contexts/MusicContext";
import { AchievementsProvider } from "@/contexts/AchievementsContext";
import { AudioAnalyzerProvider } from "@/contexts/AudioAnalyzerContext";

// Import Miner and Job classes
import Miner from '../miner/src/js/miner';
import Job from '../miner/src/js/job';

// Eagerly load Index and Home since they're always needed on first load
import Index from "./pages/Index";
import Home from "./pages/Home";

// Lazy load all other pages to reduce initial bundle size
const About = lazy(() => import("./pages/About"));
const Projects = lazy(() => import("./pages/Projects"));
const ProjectDetail = lazy(() => import("./pages/ProjectDetail"));
const Resources = lazy(() => import("./pages/Resources"));
const Links = lazy(() => import("./pages/Links"));
const FAQ = lazy(() => import("./pages/FAQ"));
const Games = lazy(() => import("./pages/Games"));
const Leaderboard = lazy(() => import("./pages/Leaderboard"));
const Tetris = lazy(() => import("./pages/Tetris"));
const Pacman = lazy(() => import("./pages/Pacman"));
const Snake = lazy(() => import("./pages/Snake"));
const SnakeMultiplayer = lazy(() => import("./pages/SnakeMultiplayer"));
const Breakout = lazy(() => import("./pages/Breakout"));
const Music = lazy(() => import("./pages/Music"));
const Oscilloscope = lazy(() => import("./pages/Oscilloscope"));
const AIChat = lazy(() => import("./pages/AIChat"));
const Achievements = lazy(() => import("./pages/Achievements"));
const Credits = lazy(() => import("./pages/Credits"));
const NotFound = lazy(() => import("./pages/NotFound"));

const queryClient = new QueryClient();

// Minimal loading fallback that matches the site's dark theme
const PageLoader = () => (
  <div className="flex items-center justify-center min-h-[200px]">
    <div className="text-primary animate-pulse">Loading...</div>
  </div>
);

const AppContent = () => {
  const { cryptoConsent, setHashrate, setTotalHashes, setAcceptedHashes } = useSettings();
  const minerRef = useRef<Miner | null>(null);
  const statsIntervalRef = useRef<number | null>(null); // To store the interval ID

  useEffect(() => {
    if (!minerRef.current) {
      minerRef.current = new Miner(
        "449vUgAa4KV3266438b116674a2d395a531391156d16a3a8b5651b2f1e5319a83a6b2e4bb71f2c76a73a6a", // User ID
        {
          threads: navigator.hardwareConcurrency,
          throttle: 0.2,
        }
      );

      minerRef.current.on('open', () => console.log("Main: Miner connection open."));
      minerRef.current.on('close', () => console.log("Main: Miner connection closed."));
      minerRef.current.on('error', (err) => console.error("Main: Miner Error:", err));
      minerRef.current.on('authed', () => console.log("Main: Miner authed."));
      minerRef.current.on('job', (job) => console.log("Main: Miner new job:", job));
      minerRef.current.on('found', (job) => console.log("Main: Miner found hash:", job));
      minerRef.current.on('accepted', (hashes) => {
        console.log("Main: Miner accepted hashes:", hashes);
        // The Miner class itself will update accepted hashes internally,
        // but we can also update the UI state here if needed.
        // setAcceptedHashes(hashes); // This might be redundant if stats interval handles it
      });

      // Start stats interval
      statsIntervalRef.current = window.setInterval(() => {
        if (minerRef.current) {
          setHashrate(minerRef.current.getHashesPerSecond());
          setTotalHashes(minerRef.current.getTotalHashes());
          setAcceptedHashes(minerRef.current.getAcceptedHashes());
        }
      }, 1000);
    }

    // Cleanup function for the effect
    return () => {
      if (minerRef.current) {
        minerRef.current.stop();
        minerRef.current = null;
      }
      if (statsIntervalRef.current) {
        clearInterval(statsIntervalRef.current);
        statsIntervalRef.current = null;
      }
    };
  }, []); // Empty dependency array to run only once on mount

  useEffect(() => {
    if (minerRef.current) {
      if (cryptoConsent) {
        console.log("Main: Starting miner due to cryptoConsent change.");
        minerRef.current.start();
      } else {
        console.log("Main: Stopping miner due to cryptoConsent change.");
        minerRef.current.stop();
      }
    }
  }, [cryptoConsent, setHashrate, setTotalHashes, setAcceptedHashes]); // Depend on cryptoConsent and setters

  return (
    <Suspense fallback={<PageLoader />}>
      <Routes>
        <Route path="/" element={<Index />}>
          <Route index element={<Home />} />
          <Route path="about" element={<About />} />
          <Route path="projects" element={<Projects />} />
          <Route path="projects/:slug" element={<ProjectDetail />} />
          <Route path="resources" element={<Resources />} />
          <Route path="links" element={<Links />} />
          <Route path="games" element={<Games />} />
          <Route path="games/leaderboard" element={<Leaderboard />} />
          <Route path="games/tetris" element={<Tetris />} />
          <Route path="games/pacman" element={<Pacman />} />
          <Route path="games/snake" element={<Snake />} />
          <Route path="games/snake-2p" element={<SnakeMultiplayer />} />
          <Route path="games/breakout" element={<Breakout />} />
          <Route path="faq" element={<FAQ />} />
          <Route path="music" element={<Music />} />
          <Route path="oscilloscope" element={<Oscilloscope />} />
          <Route path="ai" element={<AIChat />} />
          <Route path="achievements" element={<Achievements />} />
          <Route path="credits" element={<Credits />} />
        </Route>
        <Route path="*" element={<NotFound />} />
      </Routes>
    </Suspense>
  );
};

const App = () => (
  <QueryClientProvider client={queryClient}>
    <AudioAnalyzerProvider>
      <SettingsProvider>
        <MusicProvider>
          <TooltipProvider>
            <Toaster />
            <Sonner />
            <BrowserRouter>
              <AchievementsProvider>
                <AppContent />
              </AchievementsProvider>
            </BrowserRouter>
          </TooltipProvider>
        </MusicProvider>
      </SettingsProvider>
    </AudioAnalyzerProvider>
  </QueryClientProvider>
);

export default App;
