/**
 * # cli/backend/select — pick the ExecutionBackend from the global flags + env.
 *
 * Local is the DEFAULT (node-light construction). `--api <url>` > `KESTREL_API` env
 * selects the RemoteBackend. Construction pulls no heavy runtime, so threading a
 * backend from `main` never breaks the light command path.
 */

import type { GlobalFlags } from "../context.ts";
import type { ExecutionBackend } from "./index.ts";
import { LocalBackend } from "./local.ts";
import { RemoteBackend, DEFAULT_API } from "./remote.ts";
import { loadCredential, loadKeypair } from "../credentials.ts";
import { mintRequestJwt } from "../keypair.ts";

interface Env {
  readonly [k: string]: string | undefined;
}

/** Local is the DEFAULT. `--api <url>` > `KESTREL_API` env selects remote.
 *  A bare `--api` (or `--api default`) uses the canonical base.
 *
 *  When a REGISTERED-agent credential (`kestrel register`, kestrel-markets-0t0) is
 *  stored for the SAME api base, it is presented as the bearer so remote calls run as
 *  the registered agent instead of self-minting an anonymous trial each time. A
 *  credential minted for a DIFFERENT host is ignored (host-scoped, fail-safe). Loading
 *  is best-effort (fail-quiet) — a missing/corrupt file just falls back to the trial. */
export function resolveBackend(globals: GlobalFlags, env: Env): ExecutionBackend {
  const raw = globals.api ?? env.KESTREL_API;
  if (raw === undefined) return new LocalBackend();
  const baseUrl = (raw === "" || raw === "default" ? DEFAULT_API : raw).replace(/\/+$/, "");

  // KEYPAIR-JWT auth (kestrel-markets-0t0 slice 2) takes PRECEDENCE over the bearer: when an
  // enrolled keyfile (`kestrel register --keypair`) is host-scoped to THIS base, mint a fresh
  // short-lived JWT per request (a possession proof signed by the enrolled private key) instead
  // of replaying the durable capability. Minted on demand, so it needs no freshness check — an
  // enrolled key does not expire like the 1h kcap. Absent ⇒ the kcap path below runs unchanged.
  const keypair = loadKeypair();
  if (keypair !== undefined && keypair.api.replace(/\/+$/, "") === baseUrl) {
    const jwtSigner = () =>
      mintRequestJwt({
        privateJwk: keypair.private_jwk,
        subject: keypair.subject,
        audience: keypair.audience,
        ttlSec: keypair.max_ttl_seconds,
      });
    return new RemoteBackend({ baseUrl, jwtSigner });
  }

  const cred = loadCredential();
  // Present the stored credential only when it is host-scoped to THIS base AND still
  // valid: an EXPIRED credential is ignored so a stale token can never wedge remote
  // calls (the platform would 401 it) — the backend falls back to a fresh anonymous
  // trial instead. A malformed/absent expiry is treated as expired (fail-safe).
  const fresh = cred !== undefined && Number.isFinite(Date.parse(cred.expiry)) && Date.parse(cred.expiry) > Date.now();
  const bearer = cred !== undefined && fresh && cred.api.replace(/\/+$/, "") === baseUrl ? cred.capability : undefined;
  return new RemoteBackend({ baseUrl, ...(bearer !== undefined ? { bearer } : {}) });
}
