import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { api } from './api';
import { getSocket, refreshSocketSession } from './socket';

const AuthContext = createContext(null);

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

  const refresh = useCallback(async () => {
    try {
      const data = await api.me();
      setUser(data.user);
    } catch {
      setUser(null);
    } finally {
      setLoading(false);
    }
  }, []);

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

  // Keep Socket.IO presence in sync with HTTP session (login / logout / boot).
  useEffect(() => {
    if (loading) return;
    refreshSocketSession();
  }, [loading, user?.id]);

  useEffect(() => {
    const socket = getSocket();
    const onReset = () => {
      refresh();
    };
    socket.on('server:prestige-reset', onReset);
    return () => {
      socket.off('server:prestige-reset', onReset);
    };
  }, [refresh]);

  const login = async (username, password) => {
    const data = await api.login(username, password);
    setUser(data.user);
    return data.user;
  };

  const register = async (username, password) => {
    const data = await api.register(username, password);
    setUser(data.user);
    return data.user;
  };

  const adminLogin = async (username, password) => {
    const data = await api.adminLogin(username, password);
    setUser(data.user);
    return data.user;
  };

  const logout = async () => {
    await api.logout();
    setUser(null);
  };

  const updateBalance = useCallback((balance) => {
    setUser((prev) => (prev ? { ...prev, balance } : prev));
  }, []);

  const patchUser = useCallback((partial) => {
    setUser((prev) => {
      if (!prev) return prev;
      let changed = false;
      for (const key of Object.keys(partial)) {
        if (prev[key] !== partial[key]) {
          changed = true;
          break;
        }
      }
      return changed ? { ...prev, ...partial } : prev;
    });
  }, []);

  return (
    <AuthContext.Provider
      value={{
        user,
        loading,
        login,
        register,
        adminLogin,
        logout,
        refresh,
        updateBalance,
        patchUser,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  return useContext(AuthContext);
}
