import {
  createContext,
  useContext,
  useState,
  useEffect,
  useCallback,
  type ReactNode,
} from 'react';
import { getMe, login as apiLogin, logout as apiLogout } from '../api/auth';
import { setOnUnauthorized } from '../api/client';

interface AuthState {
  user: { login: string } | null;
  loading: boolean;
  error: string | null;
  login: (username: string, password: string) => Promise<void>;
  logout: () => Promise<void>;
}

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

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<{ login: string } | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const clearUser = useCallback(() => {
    setUser(null);
  }, []);

  useEffect(() => {
    setOnUnauthorized(clearUser);
    getMe()
      .then((me) => setUser({ login: me.login }))
      .catch(() => setUser(null))
      .finally(() => setLoading(false));
  }, [clearUser]);

  const login = useCallback(async (username: string, password: string) => {
    setError(null);
    try {
      await apiLogin({ login: username, password });
      const me = await getMe();
      setUser({ login: me.login });
    } catch (e: unknown) {
      const msg = e instanceof Error && e.message === 'Failed to fetch'
        ? 'Сервер недоступен. Проверьте, что backend запущен и NPM проксирует /api на порт 3000.'
        : e instanceof Error
          ? e.message
          : 'Ошибка входа';
      setError(msg);
      throw e;
    }
  }, []);

  const logout = useCallback(async () => {
    try {
      await apiLogout();
    } finally {
      setUser(null);
    }
  }, []);

  return (
    <AuthContext.Provider value={{ user, loading, error, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

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