import type { User } from "@/entities/user";
import { client, wallets } from "@/shared/lib/web3";
import { useState } from "react";
import type React from "react";
import { useEffect } from "react";
import { Outlet } from "react-router";
import {
  useActiveAccount,
  useActiveWallet,
  useActiveWalletConnectionStatus,
  useAutoConnect,
} from "thirdweb/react";
import { useAuthSlice } from "../model/authSlice";

export const AuthProvider: React.FC = () => {
  const { setAddress, setStatus, setUser, clear, ticketPoll, clearTicketPoll } =
    useAuthSlice();
  const [walletChanged, setWalletChanged] = useState(false);

  const wallet = useActiveWallet();
  const account = useActiveAccount();
  const walletConnectionStatus = useActiveWalletConnectionStatus();
  useEffect(() => {
    if (wallet == null) {
      return;
    }
    wallet.subscribe("accountChanged", () => {
      console.log("account changed");
      setWalletChanged(true);
    });
  }, [wallet]);

  useAutoConnect({
    client,
    wallets,
    onConnect: (connecting) => console.log("onConnect", connecting),
    timeout: 5000,
  });

  useEffect(() => {
    const address = account?.address?.toLowerCase() ?? null;
    if (!address) {
      // Avoid treating transient disconnects/reconnects (common during WalletConnect flows)
      // as an app logout.
      if (
        walletConnectionStatus === "connecting" ||
        walletConnectionStatus === "unknown"
      ) {
        return;
      }
      if (walletConnectionStatus === "disconnected") clear();
      return;
    }

    const syncUser = async () => {
      setAddress(address);
      setStatus("connected");
      setWalletChanged(false);

      const url = new URL(
        "/api/users/current/",
        import.meta.env.PUBLIC_API_HOST,
      );
      url.searchParams.set("address", address);
      const resp = await fetch(url.toString(), { credentials: "include" });
      if (!resp.ok) {
        setUser(null);
        return;
      }
      setUser((await resp.json()) as User);
    };

    void syncUser();
  }, [
    account?.address,
    clear,
    setAddress,
    setStatus,
    setUser,
    walletChanged,
    walletConnectionStatus,
  ]);

  useEffect(() => {
    const address = account?.address?.toLowerCase() ?? null;
    if (!address) return;
    if (!ticketPoll) return;
    if (walletConnectionStatus !== "connected") return;

    const startedAt = ticketPoll.startedAtMs;
    const maxMs = 90_000;
    const intervalMs = 2_000;

    let stopped = false;
    const ac = new AbortController();

    const tick = async () => {
      if (stopped) return;
      if (Date.now() - startedAt > maxMs) {
        clearTicketPoll();
        return;
      }

      try {
        const url = new URL(
          "/api/users/current/",
          import.meta.env.PUBLIC_API_HOST,
        );
        url.searchParams.set("address", address);

        const resp = await fetch(url.toString(), {
          credentials: "include",
          signal: ac.signal,
        });
        if (!resp.ok) return;

        const nextUser = (await resp.json()) as User;
        setUser(nextUser);

        const eventTickets = (nextUser.tickets ?? []).filter(
          (t) => t.eventId === ticketPoll.eventId,
        );
        const ok =
          ticketPoll.targetCount == null
            ? eventTickets.length > 0
            : eventTickets.length >= ticketPoll.targetCount;
        if (ok) clearTicketPoll();
      } catch (e) {
        // Ignore transient network errors; the loop will retry.
        if (import.meta.env.DEV) console.log("ticket poll failed", e);
      }
    };

    void tick();
    const id = window.setInterval(() => void tick(), intervalMs);

    return () => {
      stopped = true;
      ac.abort();
      window.clearInterval(id);
    };
  }, [
    account?.address,
    clearTicketPoll,
    setUser,
    ticketPoll,
    walletConnectionStatus,
  ]);

  return <Outlet />;
};

Graph