/**
 * Fastify test helpers — inject wrappers and assertion utilities.
 *
 * Usage:
 * ```ts
 * import { injectGet, injectPost, expectHealthOk } from '@bytelyst/testing';
 * const res = await injectGet(app, '/health');
 * expectHealthOk(res, 'platform-service');
 * ```
 */

import type { FastifyInstance } from 'fastify';

interface InjectResult {
  statusCode: number;
  payload: string;
  headers: Record<string, string | string[] | undefined>;
  json: () => unknown;
}

/** Inject a GET request into a Fastify instance */
export async function injectGet(
  app: FastifyInstance,
  url: string,
  headers?: Record<string, string>
): Promise<InjectResult> {
  return app.inject({ method: 'GET', url, headers }) as unknown as Promise<InjectResult>;
}

/** Inject a POST request with JSON body into a Fastify instance */
export async function injectPost(
  app: FastifyInstance,
  url: string,
  body: unknown,
  headers?: Record<string, string>
): Promise<InjectResult> {
  return app.inject({
    method: 'POST',
    url,
    payload: body as string,
    headers: { 'content-type': 'application/json', ...headers },
  }) as unknown as Promise<InjectResult>;
}

/** Inject a PATCH request with JSON body into a Fastify instance */
export async function injectPatch(
  app: FastifyInstance,
  url: string,
  body: unknown,
  headers?: Record<string, string>
): Promise<InjectResult> {
  return app.inject({
    method: 'PATCH',
    url,
    payload: body as string,
    headers: { 'content-type': 'application/json', ...headers },
  }) as unknown as Promise<InjectResult>;
}

/** Inject a DELETE request into a Fastify instance */
export async function injectDelete(
  app: FastifyInstance,
  url: string,
  headers?: Record<string, string>
): Promise<InjectResult> {
  return app.inject({ method: 'DELETE', url, headers }) as unknown as Promise<InjectResult>;
}

/** Assert a health check response has the correct shape */
export function expectHealthOk(res: InjectResult, serviceName: string): void {
  const body = JSON.parse(res.payload);
  if (res.statusCode !== 200) throw new Error(`Expected 200, got ${res.statusCode}`);
  if (body.status !== 'ok') throw new Error(`Expected status "ok", got "${body.status}"`);
  if (body.service !== serviceName)
    throw new Error(`Expected service "${serviceName}", got "${body.service}"`);
  if (!body.timestamp) throw new Error('Missing timestamp in health response');
  if (!body.requestId) throw new Error('Missing requestId in health response');
}

export type { InjectResult };
