'use client';

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react';
import { useRouter } from 'next/navigation';

import type { AuthSession } from './AuthService';

type AuthContextValue = {
  session: AuthSession | null;
  loading: boolean;
  login: (returnTo?: string) => void;
  logout: () => Promise<void>;
  refreshSession: () => Promise<void>;
};

const AuthContext = createContext<AuthContextValue | undefined>(undefined);

interface AuthProviderProps {
  initialSession?: AuthSession | null;
  children: ReactNode;
}

export function AuthProvider({ initialSession = null, children }: AuthProviderProps) {
  const router = useRouter();
  const [session, setSession] = useState<AuthSession | null>(initialSession);
  const [loading, setLoading] = useState(false);

  const fetchSession = useCallback(async () => {
    try {
      const res = await fetch('/api/auth/session', {
        method: 'GET',
        credentials: 'include',
      });

      if (!res.ok) {
        setSession(null);
        return;
      }

      const data = (await res.json()) as { session: AuthSession | null };
      setSession(data.session ?? null);
    } catch {
      setSession(null);
    }
  }, []);

  const refreshSession = useCallback(async () => {
    await fetchSession();
  }, [fetchSession]);

  useEffect(() => {
    fetchSession();
  }, [fetchSession]);

  const login = useCallback(
    (returnTo?: string) => {
      const search = new URLSearchParams();
      if (returnTo) {
        search.set('returnTo', returnTo);
      }

      const target = search.toString()
        ? `/auth/iracing?${search.toString()}`
        : '/auth/iracing';

      router.push(target);
    },
    [router],
  );

  const logout = useCallback(async () => {
    setLoading(true);
    try {
      await fetch('/api/auth/logout', {
        method: 'POST',
        credentials: 'include',
      });
      setSession(null);
      router.push('/');
      router.refresh();
    } finally {
      setLoading(false);
    }
  }, [router]);

  const value = useMemo(
    () => ({
      session,
      loading,
      login,
      logout,
      refreshSession,
    }),
    [session, loading, login, logout, refreshSession],
  );

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

export function useAuth(): AuthContextValue {
  const ctx = useContext(AuthContext);
  if (!ctx) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return ctx;
}