// Centralised response helpers so every route handler returns the same
// JSON shape. Controllers throw HttpError or ZodError, and `apiHandler`
// turns those into proper status codes. This is the part that keeps
// the route files genuinely thin.

import { NextResponse } from 'next/server';
import { ZodError } from 'zod';
import { HttpError } from '@/lib/auth/session';

export type ApiSuccess<T> = { ok: true; data: T };
export type ApiFailure = { ok: false; error: string; details?: unknown };

export function ok<T>(data: T, status = 200): NextResponse<ApiSuccess<T>> {
  return NextResponse.json({ ok: true, data }, { status });
}

export function fail(error: string, status = 400, details?: unknown): NextResponse<ApiFailure> {
  return NextResponse.json({ ok: false, error, details }, { status });
}

// Wraps an async controller function. If it throws, we map known error
// types to clean responses. Unknown errors become 500 without leaking
// the stack trace to the client.
export async function apiHandler<T>(
  fn: () => Promise<NextResponse<ApiSuccess<T>>>
): Promise<NextResponse<ApiSuccess<T> | ApiFailure>> {
  try {
    return await fn();
  } catch (err) {
    if (err instanceof HttpError) {
      return fail(err.message, err.status);
    }
    if (err instanceof ZodError) {
      return fail('Validation failed', 422, err.flatten());
    }
    console.error('Unhandled API error:', err);
    return fail('Internal server error', 500);
  }
}
