/**
 * Device-bound URL emission helper.
 *
 * A device-bound URL is one whose intent is "the device running the Maxy
 * platform needs to open this URL so its local state machine can progress"
 * — as opposed to a generic external URL that opens wherever the operator
 * is viewing the chat from.
 *
 * The contract: tool results that want a URL to open on the device
 * embed a fenced markdown code block with language identifier
 * `maxy-device-url`, containing a JSON payload { url, intent, hostname? }.
 * The chat UI dispatches on the language identifier (alongside `mermaid`)
 * and renders the block as a button that navigates the device's VNC
 * browser via CDP.
 *
 * See `.docs/web-chat.md` § URL rendering contract for the full spec.
 *
 * This module is the single source of truth for the emit-side block
 * format. Plugin MCP tools import it so every emitter produces an
 * identical shape.
 */

export interface DeviceUrlOptions {
  /** The actual URL the device should navigate to. Must be http(s). */
  url: string;
  /** Short human-readable label shown on the chat UI button (e.g. "Sign in to Cloudflare"). */
  intent: string;
  /** Optional hostname of the device — used in the fallback UI when VNC is unreachable. */
  hostname?: string;
}

export const DEVICE_URL_LANGUAGE = "maxy-device-url";

/**
 * Build a fenced markdown code block that declares a device-bound URL.
 *
 * The returned string is meant to be concatenated into a tool-result
 * `text` content block. The chat UI parses the fence and renders a button.
 * When the chat UI is older than this contract (or rendering in a
 * fallback environment), the block degrades to a readable JSON code
 * block — no broken link, no silent swallow.
 *
 * Throws on invalid input so emit-side bugs surface at call time rather
 * than producing a malformed block that the render side has to catch.
 */
export function deviceUrlBlock(opts: DeviceUrlOptions): string {
  const { url, intent, hostname } = opts;

  if (typeof url !== "string" || url.length === 0) {
    throw new Error("[device-url] url is required");
  }
  let parsed: URL;
  try {
    parsed = new URL(url);
  } catch {
    throw new Error(`[device-url] url is not a valid URL: ${url}`);
  }
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
    throw new Error(
      `[device-url] url scheme must be http or https (got ${parsed.protocol})`,
    );
  }
  if (typeof intent !== "string" || intent.length === 0) {
    throw new Error("[device-url] intent is required and must be a non-empty string");
  }
  if (intent.length > 100) {
    throw new Error(`[device-url] intent exceeds 100 chars (got ${intent.length})`);
  }
  if (hostname !== undefined && typeof hostname !== "string") {
    throw new Error("[device-url] hostname must be a string if provided");
  }

  const payload: DeviceUrlOptions = hostname
    ? { url, intent, hostname }
    : { url, intent };

  return "```" + DEVICE_URL_LANGUAGE + "\n" + JSON.stringify(payload) + "\n```";
}
