import type { ApiFailure, ApiResult, HealthResponse, JoinSessionRequest, JoinSessionResponse, SessionDetailResponse, StartRoundRequest, StartRoundResponse } from './types'; export interface AngularHttpError { status?: number; message?: string; error?: unknown; } export interface AngularHttpClientLike { get(url: string, options?: { withCredentials?: boolean }): Promise; post(url: string, body: unknown, options?: { withCredentials?: boolean }): Promise; } export interface AngularApiClient { health(): Promise>; getSession(code: string): Promise>; joinSession(payload: JoinSessionRequest): Promise>; startRound(code: string, payload: StartRoundRequest): Promise>; } function toFailure(error: unknown): ApiFailure { const candidate = (error ?? {}) as AngularHttpError; const status = typeof candidate.status === 'number' ? candidate.status : 0; const payload = candidate.error; if (status === 0) { return { kind: 'network', status: 0, message: candidate.message ?? 'Network error while contacting API' }; } return { kind: 'http', status, message: candidate.message ?? `HTTP ${status}`, ...(payload === undefined ? {} : { payload }) }; } function normalizeCode(code: string): string { return code.trim().toUpperCase(); } function normalizeBaseUrl(baseUrl: string): string { return baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl; } function buildUrl(baseUrl: string, path: string): string { return `${normalizeBaseUrl(baseUrl)}${path}`; } async function wrap(call: () => Promise): Promise> { try { const data = await call(); return { ok: true, status: 200, data }; } catch (error: unknown) { return { ok: false, status: typeof (error as AngularHttpError)?.status === 'number' ? (error as AngularHttpError).status! : 0, error: toFailure(error) }; } } export function createAngularApiClient(http: AngularHttpClientLike, baseUrl = ''): AngularApiClient { return { health: () => wrap(() => http.get(buildUrl(baseUrl, '/healthz'), { withCredentials: true })), getSession: (code: string) => wrap(() => http.get(buildUrl(baseUrl, `/lobby/sessions/${encodeURIComponent(normalizeCode(code))}`), { withCredentials: true }) ), joinSession: (payload: JoinSessionRequest) => wrap(() => http.post( buildUrl(baseUrl, '/lobby/sessions/join'), { code: normalizeCode(payload.code), nickname: payload.nickname.trim() }, { withCredentials: true } ) ), startRound: (code: string, payload: StartRoundRequest) => wrap(() => http.post( buildUrl(baseUrl, `/lobby/sessions/${encodeURIComponent(normalizeCode(code))}/rounds/start`), payload, { withCredentials: true } ) ) }; }