import { useEffect, useState } from "react";
import { Center, Loader } from "@mantine/core";
import { ChatShell } from "./ChatShell";
import { Join } from "./Join";
import { Recover } from "./Recover";
import { WalletLogin } from "./WalletLogin";
import { Welcome } from "./Welcome";
import { api } from "./api";
import { localIdentity } from "./wallet/account";
import type { User } from "./types";

type Route = "loading" | "join" | "welcome" | "login" | "recover" | "chat";

// readJoinToken returns the invite token if the current URL is /join?token=XXX.
function readJoinToken(): string | null {
  if (window.location.pathname !== "/join") return null;
  return new URLSearchParams(window.location.search).get("token");
}

// clearUrl drops any /join?token from the address bar once consumed, so a refresh
// or a shared screenshot does not replay the (single-use) token.
function clearUrl() {
  if (window.location.pathname !== "/") {
    window.history.replaceState(null, "", "/");
  }
}

export function App() {
  const [route, setRoute] = useState<Route>("loading");
  const [user, setUser] = useState<User | null>(null);
  const [token, setToken] = useState("");
  const [storedHandle, setStoredHandle] = useState("");

  // Decide the entry screen on mount: an invite link goes straight to join; a live
  // gateway session resumes the chat; a device with a stored identity shows the
  // password unlock; an empty device shows the welcome chooser.
  useEffect(() => {
    const t = readJoinToken();
    if (t) {
      setToken(t);
      setRoute("join");
      return;
    }
    let cancelled = false;
    (async () => {
      try {
        const me = await api.me();
        if (cancelled) return;
        setUser({ id: me.endpoint, handle: me.handle || me.endpoint.slice(0, 8) });
        setRoute("chat");
        return;
      } catch {
        // no live session — fall through
      }
      const stored = await localIdentity();
      if (cancelled) return;
      if (stored) {
        setStoredHandle(stored.handle);
        setRoute("login");
      } else {
        setRoute("welcome");
      }
    })();
    return () => {
      cancelled = true;
    };
  }, []);

  const enterChat = (u: User) => {
    setUser(u);
    setRoute("chat");
    clearUrl();
  };

  const logout = () => {
    void api.logout().catch(() => {});
    setUser(null);
    // Keep the encrypted identity on the device: logging out returns to the
    // password unlock, not a full reset.
    void localIdentity().then((stored) => {
      if (stored) {
        setStoredHandle(stored.handle);
        setRoute("login");
      } else {
        setRoute("welcome");
      }
    });
  };

  switch (route) {
    case "loading":
      return (
        <Center h="100vh" bg="dark.9">
          <Loader color="brand" />
        </Center>
      );
    case "join":
      return (
        <Join
          token={token}
          onJoined={enterChat}
          onRecover={() => setRoute("recover")}
        />
      );
    case "welcome":
      return (
        <Welcome
          onJoinToken={(t) => {
            setToken(t);
            setRoute("join");
          }}
          onRecover={() => setRoute("recover")}
        />
      );
    case "login":
      return (
        <WalletLogin
          handle={storedHandle}
          onLoggedIn={enterChat}
          onRecover={() => setRoute("recover")}
        />
      );
    case "recover":
      return (
        <Recover
          onRecovered={enterChat}
          onBack={() => setRoute(storedHandle ? "login" : "welcome")}
        />
      );
    case "chat":
      return user ? (
        <ChatShell user={user} onLogout={logout} />
      ) : (
        <Center h="100vh" bg="dark.9">
          <Loader color="brand" />
        </Center>
      );
  }
}
