"use client";

import { useCallback, useEffect, useState } from "react";
import {
  fetchAuthConfig,
  loginWithRedirect,
  fetchMe,
  getValidAccessToken,
  clearTokens,
  logout,
  type AuthConfig,
} from "@/lib/auth";

interface AuthUser {
  user_id: string;
  email: string | null;
  username: string | null;
  roles: string[];
}

export function useAuth() {
  const [config, setConfig] = useState<AuthConfig | null>(null);
  const [user, setUser] = useState<AuthUser | null>(null);
  const [loading, setLoading] = useState(true);
  const [isAuthenticated, setIsAuthenticated] = useState(false);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      try {
        const cfg = await fetchAuthConfig();
        setConfig(cfg);
      } catch {
        // Config blip must not wipe an existing session.
      }

      const token = await getValidAccessToken();
      if (!token) {
        setUser(null);
        setIsAuthenticated(false);
        return;
      }

      try {
        const me = await fetchMe(token);
        setUser(me);
        setIsAuthenticated(true);
      } catch {
        // Access may have expired mid-flight — try one refresh path again.
        const retry = await getValidAccessToken();
        if (!retry || retry === token) {
          clearTokens();
          setUser(null);
          setIsAuthenticated(false);
          return;
        }
        try {
          const me = await fetchMe(retry);
          setUser(me);
          setIsAuthenticated(true);
        } catch {
          clearTokens();
          setUser(null);
          setIsAuthenticated(false);
        }
      }
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    load();
    // Keep session alive while tab is open (proactive refresh).
    const id = window.setInterval(async () => {
      const token = await getValidAccessToken();
      if (!token) {
        setUser(null);
        setIsAuthenticated(false);
        return;
      }
    }, 45_000);
    const onFocus = async () => {
      const token = await getValidAccessToken();
      if (!token) {
        setUser(null);
        setIsAuthenticated(false);
      }
    };
    const onVis = async () => {
      if (document.visibilityState !== "visible") return;
      const token = await getValidAccessToken();
      if (!token) {
        setUser(null);
        setIsAuthenticated(false);
      }
    };
    window.addEventListener("focus", onFocus);
    document.addEventListener("visibilitychange", onVis);
    return () => {
      window.clearInterval(id);
      window.removeEventListener("focus", onFocus);
      document.removeEventListener("visibilitychange", onVis);
    };
  }, [load]);

  const login = async (redirectPath?: string) => {
    await loginWithRedirect(redirectPath);
  };

  const signOut = async () => {
    const cfg = config || (await fetchAuthConfig());
    await logout(cfg);
  };

  return { user, config, loading, isAuthenticated, login, signOut, reload: load };
}
