import type { ApiError, AuthUser } from './auth-types';

export class AuthClientError extends Error {
  constructor(
    message: string,
    readonly statusCode: number,
    readonly kind?: 'mfa_required' | 'device_limit_exceeded',
    readonly extra?: ApiError,
  ) {
    super(message);
    this.name = 'AuthClientError';
  }
}

async function handleJson<T>(res: Response): Promise<T> {
  if (res.status === 204) return undefined as T;
  const data = await res.json().catch(() => null);
  if (!res.ok) {
    const err = data as ApiError | null;
    const message = err?.message
      ? Array.isArray(err.message)
        ? err.message.join('\n')
        : err.message
      : `Request failed (${res.status})`;
    throw new AuthClientError(message, res.status, err?.kind, err ?? undefined);
  }
  return data as T;
}

export const authClient = {
  async login(
    email: string,
    password: string,
    mfaCode?: string,
  ): Promise<{ user: AuthUser }> {
    const res = await fetch('/api/auth/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, password, ...(mfaCode && { mfaCode }) }),
    });
    return handleJson<{ user: AuthUser }>(res);
  },
  async logout(): Promise<void> {
    await fetch('/api/auth/logout', { method: 'POST' });
  },
  async me(): Promise<{ user: AuthUser | null }> {
    const res = await fetch('/api/auth/me', { cache: 'no-store' });
    if (res.status === 401) return { user: null };
    return handleJson<{ user: AuthUser }>(res);
  },
};
