import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
import path from 'node:path';
import test from 'node:test';

const root = path.resolve(import.meta.dirname, '..');
const read = relativePath => fs.readFile(path.join(root, relativePath), 'utf8');

test('complete REST API documentation is kept outside the README', async () => {
  const readme = await read('README.md');
  const api = await read('docs/REST-API.md');

  assert.match(readme, /\[.*REST-API.*\]\(docs\/REST-API\.md\)/i);
  assert.doesNotMatch(readme, /^## REST-API$/m);
  assert.doesNotMatch(readme, /curl .*\/api\//);

  for (const endpoint of [
    'GET /api/health',
    'GET /api/routes',
    'GET /api/routes/:id',
    'GET /api/routes/:id/gpx',
    'GET /api/routes/:id/pois',
    'GET /api/routes/:routeId/pois/:poiId',
    'POST /api/routes',
    'PUT /api/routes/:id',
    'POST /api/routes/:id/append',
    'POST /api/routes/:id/pois',
    'PUT /api/routes/:routeId/pois/:poiId',
    'DELETE /api/routes/:routeId/pois/:poiId',
    'GET /api/routes/:routeId/pois/:poiId/pictures',
    'GET /api/routes/:routeId/pois/:poiId/pictures/:pictureId',
    'POST /api/routes/:routeId/pois/:poiId/pictures',
    'PUT /api/routes/:routeId/pois/:poiId/pictures/:pictureId',
    'DELETE /api/routes/:routeId/pois/:poiId/pictures/:pictureId',
    'GET /api/routes/:routeId/pois/:poiId/audio',
    'POST /api/routes/:routeId/pois/:poiId/audio',
    'PUT /api/routes/:routeId/pois/:poiId/audio',
    'DELETE /api/routes/:routeId/pois/:poiId/audio',
    'DELETE /api/routes/:id',
    'POST /api/routes/:id/restore'
  ]) {
    assert.ok(api.includes(endpoint), `missing API documentation: ${endpoint}`);
  }

  for (const parameter of [
    'lat', 'lon', 'radiusKm', 'includeDeleted', 'gpx', 'name', 'slug',
    'description', 'schoolName', 'title', 'triggerRadiusM', 'sequence',
    'picture', 'pictureId', 'caption', 'audio', 'poiId', 'metadata',
    'filename', 'base64', 'dataUrl'
  ]) {
    assert.match(api, new RegExp(`\\b${parameter}\\b`), `missing parameter documentation: ${parameter}`);
  }
});

test('POI media uploads use POI-scoped single-resource endpoints', async () => {
  const router = await read('src/routes/api.js');
  const routesService = await read('src/services/routes-service.js');
  const mediaService = await read('src/services/media-service.js');
  const api = await read('docs/REST-API.md');

  assert.match(router, /post\('\/routes\/:routeId\/pois\/:poiId\/pictures', upload\.single\('picture'\), inspectUpload\('picture', 'picture'/);
  assert.match(router, /put\('\/routes\/:routeId\/pois\/:poiId\/pictures\/:pictureId', upload\.single\('picture'\), inspectUpload\('picture', 'picture'/);
  assert.match(router, /delete\('\/routes\/:routeId\/pois\/:poiId\/pictures\/:pictureId'/);
  assert.match(router, /get\('\/routes\/:routeId\/pois\/:poiId\/audio'/);
  assert.match(router, /post\('\/routes\/:routeId\/pois\/:poiId\/audio', upload\.single\('audio'\), inspectUpload\('audio', 'audio'/);
  assert.match(router, /put\('\/routes\/:routeId\/pois\/:poiId\/audio', upload\.single\('audio'\), inspectUpload\('audio', 'audio'/);
  assert.match(router, /delete\('\/routes\/:routeId\/pois\/:poiId\/audio'/);
  assert.doesNotMatch(router, /\/routes\/:id\/(?:pictures|audio)/);
  assert.match(router, /post\('\/routes\/:id\/pois', upload\.none\(\),/);
  assert.match(router, /get\('\/routes\/:routeId\/pois\/:poiId'/);
  assert.match(router, /put\('\/routes\/:routeId\/pois\/:poiId', upload\.none\(\)/);
  assert.match(router, /delete\('\/routes\/:routeId\/pois\/:poiId'/);
  assert.doesNotMatch(router, /['"]\/pois\/:id['"]/);
  assert.doesNotMatch(routesService, /files\.images|files\.audio/);
  assert.match(mediaService, /caption/);
  assert.match(mediaService, /removeStoredFile/);
  assert.doesNotMatch(mediaService, /fields\.poiId/);
  assert.match(router, /get\('\/routes\/:id\/gpx'/);
  assert.match(router, /req\.query\.metadata === 'true'/);
  assert.doesNotMatch(router, /['"`]\/media\//);
  assert.doesNotMatch(routesService, /safeMediaUrl|\/media\//);
  assert.doesNotMatch(mediaService, /safeMediaUrl|\/media\//);
  assert.match(router, /inspectUpload/);
  assert.match(api, /Content-Type: `application\/json`/);
  assert.match(api, /`text\/json`/);
  assert.match(api, /Base64/);
});
