import React, {
  createContext,
  useState,
  useContext,
  useEffect,
  useRef,
  ReactNode,
} from "react";
import { User } from "../types";
import {
  authAPI,
  fetchCSRFToken,
  resetCSRFToken,
} from "../services/api";

interface RegisterResponse {
  verificationEmailSent?: boolean;
}

interface AuthContextType {
  user: User | null;
  loading: boolean;
  login: (email: string, password: string) => Promise<void>;
  register: (data: any) => Promise<RegisterResponse>;
  googleLogin: (code: string) => Promise<void>;
  logout: () => Promise<void>;
  updateUser: (user: User) => void;
  checkAuth: () => Promise<void>;
  showAuthModal: boolean;
  authModalMode: "login" | "signup" | "forgot-password";
  openAuthModal: (mode: "login" | "signup" | "forgot-password") => void;
  closeAuthModal: () => void;
}

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

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
};

interface AuthProviderProps {
  children: ReactNode;
}

export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);
  const [showAuthModal, setShowAuthModal] = useState(false);
  const [authModalMode, setAuthModalMode] = useState<"login" | "signup" | "forgot-password">("login");
  const isAuthenticating = useRef(false);

  const checkAuth = async () => {
    try {
      // Use the status endpoint which returns 200 for both authenticated and unauthenticated states
      const response = await authAPI.getStatus();

      if (response.data.authenticated) {
        setUser(response.data.user);
      } else {
        setUser(null);
      }
    } catch (error: any) {
      // If we get here, there's a network or server error
      setUser(null);
    }
  };

  useEffect(() => {
    // Initialize authentication
    const initializeAuth = async () => {
      try {
        // Skip CSRF token fetch and auth check if we're on the OAuth callback page
        // The callback page will handle both CSRF token fetch and authentication
        const isOAuthCallback = window.location.pathname === '/auth/google/callback';

        if (!isOAuthCallback) {
          await fetchCSRFToken();

          // Skip auth check if we're in the middle of an authentication operation
          if (!isAuthenticating.current) {
            await checkAuth();
          }
        }
      } catch (error) {
        console.error("Failed to initialize authentication:", error);
      } finally {
        setLoading(false);
      }
    };

    initializeAuth();
  }, []);

  const login = async (email: string, password: string) => {
    const response = await authAPI.login({ email, password });
    setUser(response.data.user);
    // Fetch new CSRF token after login
    await fetchCSRFToken();
  };

  const register = async (data: any): Promise<RegisterResponse> => {
    const response = await authAPI.register(data);
    setUser(response.data.user);
    // Fetch new CSRF token after registration
    await fetchCSRFToken();
    return {
      verificationEmailSent: response.data.verificationEmailSent,
    };
  };

  const googleLogin = async (code: string) => {
    isAuthenticating.current = true;
    try {
      const response = await authAPI.googleLogin(code);
      setUser(response.data.user);
      // Fetch new CSRF token after Google login
      await fetchCSRFToken();
    } finally {
      isAuthenticating.current = false;
    }
  };

  const logout = async () => {
    try {
      await authAPI.logout();
      setUser(null);
      // Reset CSRF token on logout
      resetCSRFToken();
      // Redirect to home page after logout
      window.location.href = "/";
    } catch (error) {
      console.error("Logout failed:", error);
      // Even if logout fails, clear local state and CSRF token
      setUser(null);
      resetCSRFToken();
    }
  };

  const updateUser = (user: User) => {
    setUser(user);
  };

  const openAuthModal = (mode: "login" | "signup" | "forgot-password") => {
    setAuthModalMode(mode);
    setShowAuthModal(true);
  };

  const closeAuthModal = () => {
    setShowAuthModal(false);
  };

  return (
    <AuthContext.Provider
      value={{
        user,
        loading,
        login,
        register,
        googleLogin,
        logout,
        updateUser,
        checkAuth,
        showAuthModal,
        authModalMode,
        openAuthModal,
        closeAuthModal,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};
