import React, {
  createContext,
  useContext,
  useState,
  useEffect,
  useRef,
} from "react";
import * as SecureStore from "expo-secure-store";
import { SERVER_ORIGIN } from "../config";
import { setAuthToken } from "../lib/apiFetch";

export interface AuthUser {
  id: string;
  provider: "google" | "apple";
  email: string | null;
  name: string | null;
  avatarUrl: string | null;
}

interface AuthContextType {
  user: AuthUser | null;
  /** True while the persisted session is still being restored on launch. */
  isAuthLoading: boolean;
  signInWithGoogleIdToken: (idToken: string) => Promise<void>;
  signInWithAppleIdentityToken: (
    identityToken: string,
    fullName?: string,
  ) => Promise<void>;
  signOut: () => Promise<void>;
}

const SESSION_TOKEN_KEY = "session_token";
const SESSION_USER_KEY = "session_user";

const AuthContext = createContext<AuthContextType | null>(null);

export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
  const [user, setUser] = useState<AuthUser | null>(null);
  const [isAuthLoading, setIsAuthLoading] = useState(true);
  const tokenRef = useRef<string | null>(null);

  useEffect(() => {
    (async () => {
      try {
        const [token, storedUser] = await Promise.all([
          SecureStore.getItemAsync(SESSION_TOKEN_KEY),
          SecureStore.getItemAsync(SESSION_USER_KEY),
        ]);
        if (token && storedUser) {
          tokenRef.current = token;
          setAuthToken(token);
          setUser(JSON.parse(storedUser));
        }
      } catch (e) {
        console.warn("Failed to restore session", e);
      } finally {
        setIsAuthLoading(false);
      }
    })();
  }, []);

  const persistSession = async (token: string, nextUser: AuthUser) => {
    tokenRef.current = token;
    setAuthToken(token);
    setUser(nextUser);
    await SecureStore.setItemAsync(SESSION_TOKEN_KEY, token);
    await SecureStore.setItemAsync(SESSION_USER_KEY, JSON.stringify(nextUser));
  };

  const signInWithGoogleIdToken = async (idToken: string) => {
    const res = await fetch(`${SERVER_ORIGIN}/api/auth/google`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ idToken }),
    });
    const data = await res.json();
    if (!res.ok) throw new Error(data.error || "Google sign-in failed");
    await persistSession(data.token, data.user);
  };

  const signInWithAppleIdentityToken = async (
    identityToken: string,
    fullName?: string,
  ) => {
    const res = await fetch(`${SERVER_ORIGIN}/api/auth/apple`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ identityToken, fullName }),
    });
    const data = await res.json();
    if (!res.ok) throw new Error(data.error || "Apple sign-in failed");
    await persistSession(data.token, data.user);
  };

  const signOut = async () => {
    tokenRef.current = null;
    setAuthToken(null);
    setUser(null);
    await SecureStore.deleteItemAsync(SESSION_TOKEN_KEY);
    await SecureStore.deleteItemAsync(SESSION_USER_KEY);
  };

  return (
    <AuthContext.Provider
      value={{
        user,
        isAuthLoading,
        signInWithGoogleIdToken,
        signInWithAppleIdentityToken,
        signOut,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => useContext(AuthContext)!;
