import React, { createContext, useState, useEffect, ReactNode } from "react";
import { User } from "../types";

export interface SignInOptions {
  callbackUrl?: string;
  redirect?: boolean;
  [key: string]: unknown;
}

export interface AuthSession {
  user: User | null;
  isLoading: boolean;
  isAuthenticated: boolean;
}

export interface AuthContextType extends AuthSession {
  signIn: (provider?: string, options?: SignInOptions) => Promise<void>;
  signOut: () => Promise<void>;
  updateUser: (userData: Partial<User>) => void;
}

export interface AuthProviderProps {
  children: ReactNode;
  // Adapter functions for different auth systems
  getSession?: () => Promise<{ user: User | null }>;
  signInAdapter?: (provider?: string, options?: SignInOptions) => Promise<void>;
  signOutAdapter?: () => Promise<void>;
  onAuthStateChange?: (user: User | null) => void;
  // Initial session data
  initialSession?: { user: User | null };
}

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

export { AuthContext };

export const AuthProvider: React.FC<AuthProviderProps> = ({
  children,
  getSession,
  signInAdapter,
  signOutAdapter,
  onAuthStateChange,
  initialSession,
}) => {
  const [user, setUser] = useState<User | null>(initialSession?.user || null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const initializeAuth = async () => {
      if (getSession) {
        try {
          const session = await getSession();
          setUser(session.user);
          onAuthStateChange?.(session.user);
        } catch (error) {
          console.error("Failed to get session:", error);
          setUser(null);
          onAuthStateChange?.(null);
        }
      }
      setIsLoading(false);
    };

    initializeAuth();
  }, [getSession, onAuthStateChange]);

  const signIn = async (provider?: string, options?: SignInOptions) => {
    if (signInAdapter) {
      setIsLoading(true);
      try {
        await signInAdapter(provider, options);
        // Refresh session after sign in
        if (getSession) {
          const session = await getSession();
          setUser(session.user);
          onAuthStateChange?.(session.user);
        }
      } catch (error) {
        console.error("Sign in failed:", error);
        throw error;
      } finally {
        setIsLoading(false);
      }
    } else {
      throw new Error("Sign in adapter not provided");
    }
  };

  const signOut = async () => {
    if (signOutAdapter) {
      setIsLoading(true);
      try {
        await signOutAdapter();
        setUser(null);
        onAuthStateChange?.(null);
      } catch (error) {
        console.error("Sign out failed:", error);
        throw error;
      } finally {
        setIsLoading(false);
      }
    } else {
      throw new Error("Sign out adapter not provided");
    }
  };

  const updateUser = (userData: Partial<User>) => {
    if (user) {
      const updatedUser = { ...user, ...userData };
      setUser(updatedUser);
      onAuthStateChange?.(updatedUser);
    }
  };

  const value: AuthContextType = {
    user,
    isLoading,
    isAuthenticated: !!user,
    signIn,
    signOut,
    updateUser,
  };

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