/**
 * x402 Hono middleware — reusable payment gate for rSpace modules.
 *
 * When X402_PAY_TO env is set, protects routes with x402 micro-transactions.
 * When not set, acts as a no-op passthrough.
 */

import type { Context, Next, MiddlewareHandler } from "hono";

export interface X402Config {
  payTo: string;
  network: string;
  amount: string;
  facilitatorUrl: string;
  resource?: string;
  description?: string;
}

/**
 * Create x402 payment middleware for Hono routes.
 * Returns null if X402_PAY_TO is not configured (disabled).
 */
export function createX402Middleware(config: X402Config): MiddlewareHandler {
  return async (c: Context, next: Next) => {
    const paymentHeader = c.req.header("X-PAYMENT");

    if (!paymentHeader) {
      // Return 402 with payment requirements
      const requirements = {
        x402Version: 1,
        scheme: "exact",
        network: config.network,
        maxAmountRequired: config.amount,
        resource: config.resource || c.req.url,
        description: config.description || "Payment required for upload",
        payTo: config.payTo,
        maxTimeoutSeconds: 300,
      };

      return c.json(
        { error: "Payment Required", paymentRequirements: requirements },
        402,
        { "X-PAYMENT-REQUIREMENTS": JSON.stringify(requirements) }
      );
    }

    // Verify payment via facilitator
    try {
      const verifyRes = await fetch(`${config.facilitatorUrl}/verify`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          payment: paymentHeader,
          requirements: {
            scheme: "exact",
            network: config.network,
            maxAmountRequired: config.amount,
            payTo: config.payTo,
          },
        }),
      });

      if (!verifyRes.ok) {
        const err = await verifyRes.text();
        return c.json({ error: "Payment verification failed", details: err }, 402);
      }

      const result = await verifyRes.json() as { valid?: boolean };
      if (!result.valid) {
        return c.json({ error: "Payment invalid or insufficient" }, 402);
      }

      // Payment valid — store tx info for downstream handlers
      c.set("x402Payment", paymentHeader);
      await next();
    } catch (e) {
      console.error("[x402] Verification error:", e);
      return c.json({ error: "Payment verification service unavailable" }, 503);
    }
  };
}

/**
 * Initialize x402 from environment variables.
 * Returns middleware or null if disabled.
 */
export function setupX402FromEnv(overrides?: Partial<X402Config>): MiddlewareHandler | null {
  const payTo = process.env.X402_PAY_TO;
  if (!payTo) {
    console.log("[x402] Disabled — X402_PAY_TO not set");
    return null;
  }

  const config: X402Config = {
    payTo,
    network: process.env.X402_NETWORK || "eip155:84532",
    amount: process.env.X402_UPLOAD_PRICE || "0.01",
    facilitatorUrl: process.env.X402_FACILITATOR_URL || "https://www.x402.org/facilitator",
    ...overrides,
  };

  console.log(`[x402] Enabled — payTo=${payTo}, network=${config.network}, amount=${config.amount}`);
  return createX402Middleware(config);
}
