// Réglages exposés à l'UI (onglet Réglages). Frontière de sécurité CENTRALE : la table `settings`
// contient aussi des SECRETS (server_secret, vapid_private). Ces routes n'exposent QUE des champs
// non sensibles et n'écrivent QUE des clés explicitement allow-listées — jamais les secrets.
import type { FastifyInstance } from 'fastify';
import type { ServerInfo, SettingsResponse, UpdateSettingsRequest } from '@arboretum/shared';
import type { Config } from '../config.js';
import { type Db, setSetting } from '../db/index.js';
import type { PushService } from '../core/push-service.js';
import { recordAudit } from '../core/audit-log.js';
import {
  SCAN_INTERVAL_KEY,
  SCAN_ROOTS_KEY,
  normalizeScanIntervalMin,
  normalizeScanRoots,
  readScanIntervalMin,
  readScanRoots,
} from '../core/scan-settings.js';

// Réglages modifiables via l'API (allow-list stricte). Les secrets ne figurent JAMAIS ici.
export function registerSettingsRoutes(
  app: FastifyInstance,
  db: Db,
  config: Config,
  serverVersion: string,
  push: PushService,
): void {
  const serverInfo = (): ServerInfo => ({
    version: serverVersion,
    port: config.port,
    bind: config.bind,
    allowedOrigins: config.allowedOrigins,
    dataDir: config.dataDir,
    vapidPublicKey: push.publicKey() || null,
    vapidContact: config.vapidContact,
  });
  const snapshot = (): SettingsResponse => ({
    settings: {
      scanRoots: readScanRoots(db),
      scanIntervalMin: readScanIntervalMin(db),
    },
    server: serverInfo(),
  });

  app.get('/api/v1/settings', async (): Promise<SettingsResponse> => snapshot());

  app.patch('/api/v1/settings', async (req, reply) => {
    const body = (req.body as Partial<UpdateSettingsRequest> | null) ?? {};
    if ('scanRoots' in body) {
      const roots = normalizeScanRoots(body.scanRoots);
      if (!roots) {
        return reply.status(400).send({ error: { code: 'BAD_REQUEST', message: 'scanRoots must be an array of ≤16 absolute, normalized paths (never "/")' } });
      }
      setSetting(db, SCAN_ROOTS_KEY, JSON.stringify(roots));
    }
    if ('scanIntervalMin' in body) {
      const interval = normalizeScanIntervalMin(body.scanIntervalMin);
      if (interval === null) {
        return reply.status(400).send({ error: { code: 'BAD_REQUEST', message: 'scanIntervalMin must be an integer between 0 and 1440' } });
      }
      setSetting(db, SCAN_INTERVAL_KEY, String(interval));
    }
    recordAudit(db, {
      actor: req.authContext?.tokenId ?? 'unknown',
      action: 'settings.update',
      details: { keys: Object.keys(body) },
    });
    return reply.send(snapshot());
  });
}
