import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { getStoredUser, storeUser, clearStoredUser } from '../../shared/lib/auth';
import type { User } from '../../shared/types/auth';

// ─────────────────────────────────────────────────────────────────────────────
// Types
// ─────────────────────────────────────────────────────────────────────────────

interface AuthContextValue {
  /** Currently authenticated user, or null when logged out */
  user: User | null;
  /** True while the initial session hydration from localStorage is pending */
  isLoading: boolean;
  /** Attempt login — returns true on success, false on invalid credentials */
  login: (email: string, password: string) => boolean;
  /** Clear session and redirect to /login */
  logout: () => void;
}

// ─────────────────────────────────────────────────────────────────────────────
// Context
// ─────────────────────────────────────────────────────────────────────────────

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

const AUTH_PATHS = ['/login', '/forgot-password', '/verify-email', '/reset-password'];

// ─────────────────────────────────────────────────────────────────────────────
// Provider
// ─────────────────────────────────────────────────────────────────────────────

/**
 * `AuthProvider` — manages authentication state for the app.
 *
 * Must be rendered **inside** `<BrowserRouter>` so that `useNavigate` is available.
 * Wrap your `<Routes>` tree with this provider to give all pages access to
 * `user`, `login`, and `logout` via `useAuth()` — no prop drilling needed.
 *
 * @example
 * ```tsx
 * <Router>
 *   <AuthProvider>
 *     <AppRoutes />
 *   </AuthProvider>
 * </Router>
 * ```
 */
export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const navigate = useNavigate();

  // Hydrate session from localStorage on mount
  useEffect(() => {
    try {
      setUser(getStoredUser());
    } finally {
      setIsLoading(false);
    }
  }, []);

  // Redirect authenticated users away from auth-only pages
  useEffect(() => {
    if (!isLoading && user && AUTH_PATHS.includes(window.location.pathname)) {
      navigate('/home', { replace: true });
    }
  }, [isLoading, user, navigate]);

  const login = useCallback(
    (email: string, password: string): boolean => {
      if (!email.trim() || !password.trim()) return false;
      const userData: User = { email };
      storeUser(userData);
      setUser(userData);
      navigate('/home');
      return true;
    },
    [navigate]
  );

  const logout = useCallback(() => {
    clearStoredUser();
    setUser(null);
    navigate('/login');
  }, [navigate]);

  return (
    <AuthContext.Provider value={{ user, isLoading, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Hook
// ─────────────────────────────────────────────────────────────────────────────

/**
 * `useAuth` — consume authentication state anywhere inside `<AuthProvider>`.
 *
 * @throws if called outside `<AuthProvider>`
 */
export function useAuth(): AuthContextValue {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be used within <AuthProvider>');
  return ctx;
}
