// ============================================================================
// @h33/mcp — HTTP middleware for attesting request/response pairs
//
// Works with Express, Hono, or any framework using (req, res, next).
// Attests every request that passes through the middleware.
// ============================================================================

import { H33Agent } from '@h33/agent';
import { createHash } from 'crypto';

/**
 * HTTP middleware that attests every request/response pair. Each request
 * produces a cryptographic receipt with the input hash and output hash
 * chained into the agent's session DAG.
 *
 * Receipt ID and verification URL are set as response headers:
 * - `X-H33-Receipt`: The receipt/node ID
 * - `X-H33-Verify`: Public verification URL
 *
 * Works with Express, Hono, or any framework with (req, res, next) pattern.
 *
 * @param agent - A started H33Agent instance
 * @returns Middleware function
 *
 * @example
 * ```typescript
 * import express from 'express';
 * import { H33Agent } from '@h33/agent';
 * import { h33Middleware } from '@h33/mcp';
 *
 * const agent = new H33Agent({
 *   name: 'API Gateway',
 *   canonicalName: 'h33.agent.acme.gateway.prod.001',
 *   tenantId: 'acme-corp',
 * });
 * await agent.start();
 *
 * const app = express();
 * app.use('/tools', h33Middleware(agent));
 *
 * app.post('/tools/search', async (req, res) => {
 *   const results = await db.search(req.body.query);
 *   res.json(results);
 *   // X-H33-Receipt and X-H33-Verify headers are set automatically
 * });
 * ```
 */
export function h33Middleware(agent: H33Agent) {
  return async (req: any, res: any, next: any) => {
    const inputHash = createHash('sha256')
      .update(JSON.stringify(req.body || {}))
      .digest('hex');

    // Intercept res.json to attest the response before sending
    const originalJson = res.json.bind(res);

    res.json = (body: any) => {
      const outputHash = createHash('sha256')
        .update(JSON.stringify(body || {}))
        .digest('hex');

      const toolName = `h33.tool.http.${req.method}.${req.path}`.toLowerCase();
      const status = res.statusCode < 400 ? 'success' : 'failed';

      agent
        .callTool(toolName, req.body, body, status)
        .then((receipt) => {
          res.set('X-H33-Receipt', receipt.receipt_id);
          res.set('X-H33-Verify', receipt.verification_url);
          originalJson(body);
        })
        .catch(() => {
          // Attestation failure must not break the response
          originalJson(body);
        });
    };

    next();
  };
}
