import { useEffect, useState } from "react";
import {
  BrowserRouter,
  Routes,
  Route,
  Navigate,
  useLocation,
  useNavigate,
} from "react-router-dom";
import { useAppStore } from "./stores/useAppStore";
import { NavBar } from "./components/molecules";
import { LoginPage, MonitoringPage, ProfilesPage, SettingsPage } from "./pages";
import * as api from "./services/api";
import {
  AUTH_REQUIRED_EVENT,
  clearStoredAuthToken,
  getStoredAuthToken,
  setStoredAuthToken,
} from "./services/auth";

type AuthMode = "probing" | "required" | "open" | "unreachable";
const AUTH_RETRY_DELAYS_MS = [1000, 2000, 4000, 8000, 15000] as const;

function AppContent() {
  const {
    setInstances,
    setProfiles,
    setAgents,
    setServerInfo,
    applyMonitoringSnapshot,
    settings,
  } = useAppStore();
  const location = useLocation();
  const navigate = useNavigate();
  const memoryMetricsEnabled = settings.monitoring?.memoryMetrics ?? false;
  // Auto-login from ?token= query parameter (e.g. from wizard URL)
  // or injected meta tag for Hugging Face Spaces integration
  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    let urlToken = params.get("token");
    if (!urlToken) {
      const meta = document.querySelector("meta[name='pinchtab-token']");
      const metaContent = meta?.getAttribute("content") || "";
      // Exclude the unreplaced template literal from injection
      if (metaContent && metaContent !== "{{PINCHTAB_TOKEN_INJECT}}") {
        urlToken = metaContent;
      }
    }
    
    if (urlToken) {
      setStoredAuthToken(urlToken);
      const clean = new URL(window.location.href);
      clean.searchParams.delete("token");
      window.history.replaceState({}, "", clean.pathname + clean.hash);
      // Let the main login flow handle reload if necessary, but actually
      // if we just updated localStorage we want to reload so state is updated
      if (getStoredAuthToken() !== urlToken) {
        window.location.reload();
      }
    }
  }, []);

  const authToken = getStoredAuthToken();
  const hasStoredToken = authToken !== "";
  const [authMode, setAuthMode] = useState<AuthMode>(
    hasStoredToken ? "required" : "probing",
  );
  const [authRetryCount, setAuthRetryCount] = useState(0);
  const dashboardAccessible = hasStoredToken || authMode === "open";
  const loginRequired = !hasStoredToken && authMode === "required";

  useEffect(() => {
    document.documentElement.setAttribute("data-site-mode", "agent");
  }, []);

  useEffect(() => {
    if (hasStoredToken) {
      setAuthMode("required");
      setAuthRetryCount(0);
      return;
    }

    if (authMode === "open" || authMode === "unreachable") {
      return;
    }

    let cancelled = false;
    api
      .probeBackendAuth()
      .then((result) => {
        if (cancelled) {
          return;
        }
        setAuthMode(result.requiresAuth ? "required" : "open");
        setAuthRetryCount(0);
        if (result.health) {
          setServerInfo(result.health);
        }
      })
      .catch((error) => {
        if (cancelled) {
          return;
        }
        console.error("Failed to probe backend auth", error);
        setAuthMode("unreachable");
      });

    return () => {
      cancelled = true;
    };
  }, [authMode, hasStoredToken, setServerInfo]);

  useEffect(() => {
    if (
      hasStoredToken ||
      authMode !== "unreachable" ||
      authRetryCount >= AUTH_RETRY_DELAYS_MS.length
    ) {
      return;
    }

    const timer = window.setTimeout(() => {
      setAuthRetryCount((count) => count + 1);
      setAuthMode("probing");
    }, AUTH_RETRY_DELAYS_MS[authRetryCount]);

    return () => {
      window.clearTimeout(timer);
    };
  }, [authMode, authRetryCount, hasStoredToken]);

  useEffect(() => {
    const handleAuthRequired = () => {
      clearStoredAuthToken();
      setAuthMode("required");
      setAuthRetryCount(0);
      navigate("/login", {
        replace: true,
        state: { from: location.pathname },
      });
    };
    window.addEventListener(AUTH_REQUIRED_EVENT, handleAuthRequired);
    return () =>
      window.removeEventListener(AUTH_REQUIRED_EVENT, handleAuthRequired);
  }, [location.pathname, navigate]);

  useEffect(() => {
    if (loginRequired && location.pathname !== "/login") {
      navigate("/login", {
        replace: true,
        state: { from: location.pathname },
      });
    }
  }, [location.pathname, loginRequired, navigate]);

  // Initial load
  useEffect(() => {
    if (!dashboardAccessible) {
      return;
    }
    const load = async () => {
      try {
        const [instances, profiles, health] = await Promise.all([
          api.fetchInstances(),
          api.fetchProfiles(),
          api.fetchHealth(),
        ]);
        setInstances(instances);
        setProfiles(profiles);
        setServerInfo(health);
      } catch (e) {
        console.error("Failed to load initial data", e);
      }
    };
    load();
  }, [dashboardAccessible, setInstances, setProfiles, setServerInfo]);

  // Subscribe to SSE events
  useEffect(() => {
    if (!dashboardAccessible) {
      return;
    }
    const unsubscribe = api.subscribeToEvents(
      {
        onInit: (agents) => {
          setAgents(agents);
        },
        onSystem: (event) => {
          console.log("System event:", event);
        },
        onAgent: (event) => {
          console.log("Agent event:", event);
        },
        onMonitoring: (snapshot) => {
          applyMonitoringSnapshot(snapshot, memoryMetricsEnabled);
        },
      },
      {
        includeMemory: memoryMetricsEnabled,
      },
    );

    return unsubscribe;
  }, [
    dashboardAccessible,
    applyMonitoringSnapshot,
    memoryMetricsEnabled,
    setAgents,
    setInstances,
    setProfiles,
  ]);

  if (!hasStoredToken && authMode === "probing") {
    return (
      <div className="flex min-h-screen items-center justify-center bg-bg-app px-4">
        <div className="rounded-sm border border-border-subtle bg-black/10 px-4 py-3 text-sm text-text-muted">
          Checking server authentication...
        </div>
      </div>
    );
  }

  if (!hasStoredToken && authMode === "unreachable") {
    const nextRetryDelay =
      authRetryCount < AUTH_RETRY_DELAYS_MS.length
        ? AUTH_RETRY_DELAYS_MS[authRetryCount]
        : null;

    return (
      <div className="flex min-h-screen items-center justify-center bg-bg-app px-4">
        <div className="max-w-md space-y-3 rounded-sm border border-border-subtle bg-black/10 px-4 py-3 text-sm text-text-muted">
          <div>
            PinchTab is restarting or unreachable.
            {nextRetryDelay !== null
              ? ` Retrying in ${Math.ceil(nextRetryDelay / 1000)}s...`
              : " Automatic retries stopped."}
          </div>
          {nextRetryDelay === null && (
            <div className="flex justify-end gap-2">
              <button
                type="button"
                className="rounded-sm border border-border-subtle px-3 py-2 text-sm text-text-primary transition-all duration-150 hover:border-primary/30 hover:bg-bg-elevated"
                onClick={() => {
                  setAuthRetryCount(0);
                  setAuthMode("probing");
                }}
              >
                Retry now
              </button>
              <button
                type="button"
                className="rounded-sm border border-border-subtle px-3 py-2 text-sm text-text-primary transition-all duration-150 hover:border-primary/30 hover:bg-bg-elevated"
                onClick={() => window.location.reload()}
              >
                Refresh
              </button>
            </div>
          )}
        </div>
      </div>
    );
  }

  if (loginRequired) {
    return (
      <Routes>
        <Route path="/login" element={<LoginPage />} />
        <Route path="*" element={<Navigate to="/login" replace />} />
      </Routes>
    );
  }

  return (
    <div className="dashboard-shell flex h-screen flex-col bg-bg-app">
      <NavBar />
      <main className="dashboard-grid flex-1 overflow-hidden">
        <Routes>
          <Route
            path="/"
            element={<Navigate to="/dashboard/monitoring" replace />}
          />
          <Route
            path="/login"
            element={<Navigate to="/dashboard/monitoring" replace />}
          />
          <Route
            path="/dashboard"
            element={<Navigate to="/dashboard/monitoring" replace />}
          />
          <Route path="/dashboard/monitoring" element={<MonitoringPage />} />
          <Route path="/dashboard/profiles" element={<ProfilesPage />} />
          <Route
            path="/dashboard/agents"
            element={<Navigate to="/dashboard/monitoring" replace />}
          />
          <Route path="/dashboard/settings" element={<SettingsPage />} />
          <Route
            path="*"
            element={<Navigate to="/dashboard/monitoring" replace />}
          />
        </Routes>
      </main>
    </div>
  );
}

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