import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import { supabase } from '../config/supabase';
import { User, Session } from '@supabase/supabase-js';

// Pass session in from the listener so we don't read a stale closure.
function getAccessToken(session: Session | null | undefined): string | undefined {
  return session?.access_token ?? undefined;
}

interface AuthUser {
  id: string;
  email: string;
  fullName?: string;
  role: string;
}

interface AuthContextType {
  user: AuthUser | null;
  session: Session | null;
  loading: boolean;
  signIn: (email: string, password: string) => Promise<{ error: any }>;
  signUp: (email: string, password: string, fullName: string, role?: string) => Promise<{ error: any }>;
  signOut: () => Promise<void>;
}

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

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (context === undefined) {
    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<AuthUser | null>(null);
  const [session, setSession] = useState<Session | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // Get initial session
    supabase.auth.getSession().then(({ data: { session } }) => {
      setSession(session);
      if (session?.user) {
        fetchUserDetails(session.user, session);
      } else {
        setLoading(false);
      }
    });

    // Listen for auth changes
    const {
      data: { subscription },
    } = supabase.auth.onAuthStateChange(async (_event, session) => {
      setSession(session);
      if (session?.user) {
        await fetchUserDetails(session.user, session);
      } else {
        setUser(null);
        setLoading(false);
      }
    });

    return () => subscription.unsubscribe();
  }, []);

  // `/auth/me` returns the canonical role + name from Postgres (metadata alone isn't enough for admin checks).
  const fetchUserDetails = async (authUser: User, currentSession?: Session | null) => {
    try {
      const API_URL = import.meta.env?.VITE_API_URL || 'http://localhost:5000/api';
      const token = getAccessToken(currentSession ?? session);
      
      const response = await fetch(`${API_URL}/auth/me`, {
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json',
        },
      });

      if (response.ok) {
        const data = await response.json();
        setUser(data.user);
      } else {
        // Fallback to basic user info if API call fails
        setUser({
          id: authUser.id,
          email: authUser.email!,
          fullName: authUser.user_metadata?.full_name,
          role: authUser.user_metadata?.role || 'user',
        });
      }
    } catch (error) {
      console.error('Error fetching user details:', error);
      // Fallback to basic user info
      setUser({
        id: authUser.id,
        email: authUser.email!,
        fullName: authUser.user_metadata?.full_name,
        role: authUser.user_metadata?.role || 'user',
      });
    } finally {
      setLoading(false);
    }
  };

  const signIn = async (email: string, password: string) => {
    const { error } = await supabase.auth.signInWithPassword({
      email,
      password,
    });
    return { error };
  };
  // Hits backend register so public.users gets inserted next to the Supabase Auth user.
  const signUp = async (email: string, password: string, fullName: string, role = 'user') => {
    try {
      const API_URL = import.meta.env?.VITE_API_URL || 'http://localhost:5000/api';
      
      const response = await fetch(`${API_URL}/auth/register`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          email,
          password,
          fullName,
          role,
        }),
      });

      if (!response.ok) {
        const errorData = await response.json();
        return { error: { message: errorData.error || 'Registration failed' } };
      }

      return { error: null };
    } catch (error) {
      console.error('Registration error:', error);
      return { error: { message: 'Network error during registration' } };
    }
  };

  const signOut = async () => {
    await supabase.auth.signOut();
  };

  const value = {
    user,
    session,
    loading,
    signIn,
    signUp,
    signOut,
  };

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