/**
 * # cli/render/offer — the 402/Offer as STRUCTURED output (ADR-0004).
 *
 * A gated remote verb returns the platform's {@link WireOfferResponse} as DATA. This
 * renders it to stdout in the active mode — the conversion moment — and the caller
 * exits `5` (PAYMENT_REQUIRED). It NEVER launches a browser, follows
 * `human_action.url`, or auto-settles: the Offer, its proof, and the settlement
 * methods are printed for the agent/human to act on. Wire shape is snake_case and
 * `offer.amount` is a {@link ../backend/wire.ts Money} object (value + asset).
 */

import type { WireOfferResponse } from "../backend/wire.ts";
import type { SettlementRequired } from "../backend/hosted.ts";
import type { OutputCtx } from "../context.ts";

/** Render a 402/Offer to stdout as DATA — the conversion moment, never a browser redirect. */
export function renderOffer(p: WireOfferResponse, ctx: OutputCtx): void {
  if (ctx.mode === "json") {
    process.stdout.write(JSON.stringify({ schema: "kestrel.payment-required/v1", ...p }) + "\n");
    return;
  }
  const o = p.offer;
  const amount = `${o.amount.value} ${o.amount.asset}`;
  const methods = p.settlement_methods.map((m) => m.method).join(",");
  const human = p.human_action?.url ?? "(none)";
  const proof = p.proof?.url ?? p.proof?.proof_id ?? "(none)";
  if (ctx.mode === "text") {
    process.stdout.write(
      `payment-required\toperation=${p.operation_id}\toffer=${o.offer_id}\tscope=${o.scope.join("+")}` +
        `\tamount=${amount}\tceiling=${o.ceiling}\tmethods=${methods}` +
        `\thuman=${human}\tproof=${proof}\n`,
    );
    return;
  }
  // human
  process.stdout.write(
    `Payment required to continue operation ${p.operation_id}\n` +
      `  earned proof: ${proof}\n` +
      `  offer ${o.offer_id}: ${amount} for scope ${o.scope.join("+")} (ceiling ${o.ceiling})\n` +
      `  machine settlement: ${p.settlement_methods.map((m) => m.method).join(", ")}\n` +
      `  human claim-and-fund: ${human}\n`,
  );
}

/**
 * Render a SPEND-BOUNDARY suspension as DATA (kestrel-e8e7). The hosted sim paused at the Spend
 * boundary (`status:"suspended"`) with a settleable Offer + a `resume` affordance inline; the
 * caller exits `5` (PAYMENT_REQUIRED). Distinct from {@link renderOffer} (the pre-drive 402
 * data-access gate): this boundary carries no `settlement_methods`, but it DOES carry the exact
 * resume call, so the output states what is owed, for what, and how to continue — the frame is
 * the docs (an agent decides its next move from this alone), never a misleading 5xx.
 */
export function renderSettlementRequired(s: SettlementRequired, ctx: OutputCtx): void {
  const o = s.offer;
  const amount = `${o.amount.value} ${o.amount.asset}`;
  const r = s.resume;
  // The wired settle URL (bead kestrel-markets-1gr8) when the platform advertised one; otherwise
  // the resume affordance is the only continuation — never fabricate a settle endpoint.
  const settleUrl = s.settlement?.url ?? "(settle the offer, then resume)";
  if (ctx.mode === "json") {
    process.stdout.write(
      JSON.stringify({
        schema: "kestrel.payment-required/v1",
        boundary: "settlement",
        operation_id: s.operationId,
        offer: o,
        ...(s.settlement !== undefined ? { settlement: s.settlement } : {}),
        resume: r,
      }) + "\n",
    );
    return;
  }
  if (ctx.mode === "text") {
    process.stdout.write(
      `payment-required\tboundary=settlement\toperation=${s.operationId}\toffer=${o.offer_id}` +
        `\tscope=${o.scope.join("+")}\tamount=${amount}\tceiling=${o.ceiling}\texpiry=${o.expiry}` +
        `\tsettle=${settleUrl}\tresume=${r.method} ${r.path}\trequires_settlement=${r.requires_settlement}` +
        `\tdetail=${r.detail}\n`,
    );
    return;
  }
  // human — the Offer's essentials legible: price, what-you-get (scope + ceiling), settle URL, expiry.
  const settleLine =
    s.settlement !== undefined
      ? `  settle at: ${s.settlement.method} ${s.settlement.url} (offer ${o.offer_id})\n`
      : `  settle the offer ${o.offer_id}, then resume\n`;
  process.stdout.write(
    `Payment required to continue operation ${s.operationId} (Spend boundary)\n` +
      `  offer ${o.offer_id}: ${amount} for scope ${o.scope.join("+")} (ceiling ${o.ceiling}, expires ${o.expiry})\n` +
      settleLine +
      `  then resume: ${r.method} ${r.path} (operation ${s.operationId}, cursor ${r.cursor})\n` +
      `  ${r.detail}\n`,
  );
}
