/** Node transport wrapper around the runtime-neutral politeness core. */
import { Agent, fetch, type Dispatcher } from "undici";
import { PoliteCore, type HttpTransport } from "./politeCore.js";

export { HttpStatusError, StorePausedError } from "./httpErrors.js";
export type {
  HttpTransport,
  HttpTransportRequest,
  HttpTransportResponse,
  PoliteCoreOptions,
} from "./politeCore.js";

const defaultDispatcher = new Agent({ allowH2: true });

export interface PoliteHttpOptions {
  minGapMs?: number;
  defaultTimeoutMs?: number;
  breakerThreshold?: number;
  breakerPauseMs?: number;
  /** Test seam — a MockAgent in tests; the shared HTTP/2 agent otherwise. */
  dispatcher?: Dispatcher;
  /** Runtime transport seam; defaults to undici with HTTP/2 enabled. */
  transport?: HttpTransport;
}

export class PoliteHttp extends PoliteCore {
  constructor(opts: PoliteHttpOptions = {}) {
    super({
      ...opts,
      transport: opts.transport ?? createUndiciTransport(opts.dispatcher ?? defaultDispatcher),
    });
  }
}

function createUndiciTransport(dispatcher: Dispatcher): HttpTransport {
  return async (request) => {
    const response = await fetch(request.url, {
      method: request.method,
      headers: request.headers,
      ...(request.body === undefined ? {} : { body: request.body }),
      dispatcher,
      redirect: "follow",
      signal: AbortSignal.timeout(request.timeoutMs),
    });
    return {
      status: response.status,
      headers: { "set-cookie": response.headers.getSetCookie() },
      body: await response.text(),
    };
  };
}
