import { createContext, useContext, useEffect, useState, useCallback } from 'react';
import api from '../api/client.js';

const AuthContext = createContext(null);

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  const loadMe = useCallback(async () => {
    const token = localStorage.getItem('cn_token');
    if (!token) {
      setLoading(false);
      return;
    }
    try {
      const { data } = await api.get('/auth/me');
      setUser(data.user);
    } catch {
      localStorage.removeItem('cn_token');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    loadMe();
  }, [loadMe]);

  const handleAuth = (data) => {
    localStorage.setItem('cn_token', data.token);
    setUser(data.user);
    return data.user;
  };

  const login = async (email, password, recaptchaToken) => {
    const { data } = await api.post('/auth/login', { email, password, recaptchaToken });
    return handleAuth(data);
  };

  // Registration no longer logs the user in — it only creates an unverified account
  // and emails a code. The user is logged in once they verify (see verifyEmail).
  const register = async (name, email, password, recaptchaToken) => {
    const { data } = await api.post('/auth/register', { name, email, password, recaptchaToken });
    return data;
  };

  // credential = Google ID token from Google Identity Services.
  const loginWithGoogle = async (credential) => {
    const { data } = await api.post('/auth/google', { credential });
    return handleAuth(data);
  };

  // --- Email OTP / password reset ---
  const verifyEmail = async (email, code) => {
    const { data } = await api.post('/auth/verify-email', { email, code });
    // A successful verification returns a token — this is the moment the user logs in.
    if (data.token) handleAuth(data);
    else if (data.user) setUser(data.user);
    return data;
  };

  const resendOtp = (email, purpose = 'EMAIL_VERIFY') =>
    api.post('/auth/resend-otp', { email, purpose }).then((r) => r.data);

  const requestPasswordReset = (email) =>
    api.post('/auth/forgot-password', { email }).then((r) => r.data);

  const resetPassword = (email, code, password) =>
    api.post('/auth/reset-password', { email, code, password }).then((r) => r.data);

  // --- Self-service account management ---
  const updateProfile = async (name) => {
    const { data } = await api.patch('/auth/profile', { name });
    setUser(data.user);
    return data.user;
  };

  const changePassword = (currentPassword, newPassword) =>
    api.post('/auth/change-password', { currentPassword, newPassword }).then((r) => r.data);

  const requestEmailChange = (newEmail) =>
    api.post('/auth/change-email', { newEmail }).then((r) => r.data);

  const verifyEmailChange = async (newEmail, code) => {
    const { data } = await api.post('/auth/change-email/verify', { newEmail, code });
    if (data.user) setUser(data.user);
    return data;
  };

  const logout = async () => {
    try {
      await api.post('/auth/logout');
    } catch {
      /* ignore */
    }
    localStorage.removeItem('cn_token');
    setUser(null);
  };

  const value = {
    user,
    loading,
    isAuthenticated: Boolean(user),
    // Admins and the super admin both reach the admin area.
    isAdmin: user?.role === 'ADMIN' || user?.role === 'SUPER_ADMIN',
    // Users & Finance are super-admin only.
    isSuperAdmin: user?.role === 'SUPER_ADMIN',
    login,
    register,
    loginWithGoogle,
    verifyEmail,
    resendOtp,
    requestPasswordReset,
    resetPassword,
    updateProfile,
    changePassword,
    requestEmailChange,
    verifyEmailChange,
    logout,
    refresh: loadMe,
  };

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

export function useAuth() {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be used within AuthProvider');
  return ctx;
}
