import { Hono } from 'hono';
import { ValidationError } from '@shade/core';
import type { KeyTransparencyService } from './kt-integration.js';
import { encodeSthForWire } from './kt-integration.js';

/**
 * Mountable routes that expose the KT log to clients and witnesses.
 *
 *   GET  /v1/kt/log_id          — public-key + log_id (operator pinning)
 *   GET  /v1/kt/sth             — latest signed tree head
 *   GET  /v1/kt/sth/:treeSize   — historical STH at a specific tree_size
 *   GET  /v1/kt/consistency     — consistency proof between two tree_sizes
 *
 * These are intentionally **anonymous & read-only** so witnesses can
 * poll without sharing identity. Rate-limiting is the prekey-server's
 * existing fetch RL bucket.
 */
export function createKTRoutes(svc: KeyTransparencyService): Hono {
  const app = new Hono();

  app.get('/log_id', (c) => {
    const logId = svc.getLogId();
    const pub = svc.getSigningPublicKey();
    return c.json({
      logId: Buffer.from(logId).toString('base64'),
      publicKey: Buffer.from(pub).toString('base64'),
    });
  });

  app.get('/sth', async (c) => {
    const sth = await svc.getLatestSTH();
    return c.json(encodeSthForWire(sth));
  });

  app.get('/sth/:treeSize', async (c) => {
    const sizeRaw = c.req.param('treeSize');
    const size = Number(sizeRaw);
    if (!Number.isFinite(size) || size < 0 || size !== Math.floor(size)) {
      throw new ValidationError('treeSize must be a non-negative integer');
    }
    const sth = await svc.getSTHByTreeSize(size);
    if (!sth) {
      return c.json({ error: 'STH not found at that tree_size', code: 'SHADE_NOT_FOUND' }, 404);
    }
    return c.json(encodeSthForWire(sth));
  });

  app.get('/consistency', async (c) => {
    const fromRaw = c.req.query('from');
    const toRaw = c.req.query('to');
    if (fromRaw === undefined) {
      throw new ValidationError('from query param required');
    }
    const from = Number(fromRaw);
    if (!Number.isFinite(from) || from < 0 || from !== Math.floor(from)) {
      throw new ValidationError('from must be a non-negative integer');
    }
    let to: number | undefined;
    if (toRaw !== undefined) {
      to = Number(toRaw);
      if (!Number.isFinite(to) || to < from || to !== Math.floor(to)) {
        throw new ValidationError('to must be an integer >= from');
      }
    }
    const result = await svc.buildConsistencyProof(from, to);
    return c.json({
      fromTreeSize: result.fromTreeSize,
      toTreeSize: result.toTreeSize,
      proof: result.proof.map((p) => Buffer.from(p).toString('base64')),
    });
  });

  return app;
}
