'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>;
};

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);

  useEffect(() => {
    if (initialSession) return;

    let cancelled = false;

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

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

        const data = (await res.json()) as { session: AuthSession | null };

        if (!cancelled) {
          setSession(data.session ?? null);
        }
      } catch {
        if (!cancelled) {
          setSession(null);
        }
      }
    }

    loadSession();

    return () => {
      cancelled = true;
    };
  }, [initialSession]);

  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,
    }),
    [session, loading, login, logout],
  );

  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;
}