import assert from 'node:assert/strict';
import test from 'node:test';
import Fastify from 'fastify';
import { registerJsonBodyParser } from '../json-body.js';
import { registerBoardRoutes } from './board.js';
import { registerNotificationRoutes } from './notification.js';

function createRouteRecorder() {
  const routes: Array<{ method: string; path: string }> = [];
  const record = (method: string) => (path: string) => {
    routes.push({ method, path });
    return undefined;
  };
  const app = {
    get: record('GET'),
    post: record('POST'),
    put: record('PUT'),
    patch: record('PATCH'),
    delete: record('DELETE'),
  };

  return {
    app: app as any,
    routes,
  };
}

test('registerJsonBodyParser treats empty json body as an empty object', async () => {
  const app = Fastify();
  registerJsonBodyParser(app);
  app.post('/json', async (request) => ({
    body: request.body,
  }));

  const response = await app.inject({
    method: 'POST',
    url: '/json',
    headers: {
      'content-type': 'application/json',
    },
    payload: '',
  });

  assert.equal(response.statusCode, 200);
  assert.deepEqual(response.json(), {
    body: {},
  });
  await app.close();
});

test('registerJsonBodyParser still rejects malformed json', async () => {
  const app = Fastify();
  registerJsonBodyParser(app);
  app.post('/json', async (request) => ({
    body: request.body,
  }));

  const response = await app.inject({
    method: 'POST',
    url: '/json',
    headers: {
      'content-type': 'application/json',
    },
    payload: '{',
  });

  assert.equal(response.statusCode, 400);
  assert.match(response.body, /valid JSON/i);
  await app.close();
});

test('registerBoardRoutes keeps setup and items compatibility routes', async () => {
  const { app, routes } = createRouteRecorder();
  await registerBoardRoutes(app);

  assert.ok(routes.some((route) => route.method === 'GET' && route.path === '/api/board/setup'));
  assert.ok(routes.some((route) => route.method === 'POST' && route.path === '/api/board/setup'));
  assert.ok(routes.some((route) => route.method === 'GET' && route.path === '/api/board/posts'));
  assert.ok(routes.some((route) => route.method === 'GET' && route.path === '/api/board/items'));
});

test('registerNotificationRoutes exposes notification message routes', async () => {
  const { app, routes } = createRouteRecorder();
  await registerNotificationRoutes(app);

  assert.ok(routes.some((route) => route.method === 'GET' && route.path === '/api/notifications/messages'));
  assert.ok(routes.some((route) => route.method === 'GET' && route.path === '/api/notifications/messages/:id'));
  assert.ok(routes.some((route) => route.method === 'POST' && route.path === '/api/notifications/messages'));
  assert.ok(routes.some((route) => route.method === 'PATCH' && route.path === '/api/notifications/messages/:id'));
  assert.ok(routes.some((route) => route.method === 'DELETE' && route.path === '/api/notifications/messages/:id'));
});
