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

/**
 * Client-side wrapper around the Next.js API route proxies. All requests
 * go to our own `/api/auth/*` endpoints — never directly to the NestJS
 * backend — so HttpOnly cookies do their job.
 */

export class AuthClientError extends Error {
  constructor(
    message: string,
    readonly statusCode: number,
    /** Structured error discriminator from the backend, when present. */
    readonly kind?: 'mfa_required' | 'device_limit_exceeded',
    /** Extra context the UI needs — device list for cap errors, etc. */
    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,
    revokeSessionId?: 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 }),
        ...(revokeSessionId && { revokeSessionId }),
      }),
    });
    return handleJson<{ user: AuthUser }>(res);
  },

  async signup(payload: {
    email: string;
    password: string;
    firstName: string;
    lastName: string;
    role: 'patient' | 'doctor';
    phone?: string;
    locale?: string;
  }): Promise<{ user: AuthUser }> {
    const res = await fetch('/api/auth/signup', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
    });
    return handleJson<{ user: AuthUser }>(res);
  },

  async logout(): Promise<void> {
    const res = await fetch('/api/auth/logout', { method: 'POST' });
    if (!res.ok && res.status !== 204) {
      throw new AuthClientError('Logout failed', res.status);
    }
  },

  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);
  },
};
