import { describe, it, expect, afterEach } from 'vitest';
import Fastify from 'fastify';
import type { FastifyInstance } from 'fastify';
import { registerHealthRoutes } from '../src/routes/health.js';

let app: FastifyInstance;

afterEach(async () => {
  if (app) await app.close();
});

describe('GET /health', () => {
  it('returns healthy when DB is up', async () => {
    app = Fastify({ logger: false });
    registerHealthRoutes(app, { checkDb: async () => true });
    await app.ready();

    const res = await app.inject({ method: 'GET', url: '/health' });
    expect(res.statusCode).toBe(200);
    const body = res.json<{ status: string; version: string; checks: { database: string } }>();
    expect(body.status).toBe('healthy');
    expect(body.version).toBeDefined();
    expect(body.checks.database).toBe('ok');
  });

  it('returns degraded when DB is down', async () => {
    app = Fastify({ logger: false });
    registerHealthRoutes(app, { checkDb: async () => false });
    await app.ready();

    const res = await app.inject({ method: 'GET', url: '/health' });
    expect(res.statusCode).toBe(503);
    const body = res.json<{ status: string; checks: { database: string } }>();
    expect(body.status).toBe('degraded');
    expect(body.checks.database).toBe('error');
  });

  it('returns degraded when DB check throws', async () => {
    app = Fastify({ logger: false });
    registerHealthRoutes(app, {
      checkDb: async () => { throw new Error('connection refused'); },
    });
    await app.ready();

    const res = await app.inject({ method: 'GET', url: '/health' });
    expect(res.statusCode).toBe(503);
  });

  it('includes uptime and timestamp', async () => {
    app = Fastify({ logger: false });
    registerHealthRoutes(app, { checkDb: async () => true });
    await app.ready();

    const res = await app.inject({ method: 'GET', url: '/health' });
    const body = res.json<{ uptime: number; timestamp: string }>();
    expect(body.uptime).toBeGreaterThan(0);
    expect(body.timestamp).toMatch(/^\d{4}-\d{2}-\d{2}T/);
  });
});

describe('GET /healthz', () => {
  it('returns ok (liveness probe)', async () => {
    app = Fastify({ logger: false });
    registerHealthRoutes(app, { checkDb: async () => true });
    await app.ready();

    const res = await app.inject({ method: 'GET', url: '/healthz' });
    expect(res.statusCode).toBe(200);
    expect(res.json<{ status: string }>().status).toBe('ok');
  });
});
