/** @module
  Fetch URLs from Agency code. Returns the response as text, JSON, or Markdown.
  Aborting tears down the in-flight request.

  ```ts
  import { fetch, fetchJSON } from "std::http"

  node main() {
    const page = fetch("https://example.com")
    const data = fetchJSON("https://api.example.com/status")
    print(page)
  }
  ```
*/

// The `__internal_*` exports remain in `lib/stdlib/http.ts` for the
// migration window.
import {
  _fetch,
  _fetchJSON,
  _fetchMarkdown,
} from "agency-lang/stdlib-lib/http.js"

effect std::http::fetch { baseUrl: string, path: string, method: string }
effect std::http::fetchJSON { baseUrl: string, path: string, method: string }
effect std::http::fetchMarkdown { baseUrl: string, path: string, method: string }

/** An HTTP request method. POST/PUT/PATCH/DELETE may carry a body; GET/HEAD do not. */
export type HttpMethod = "GET" | "HEAD" | "POST" | "PUT" | "PATCH" | "DELETE"

/**
  On abort, Agency tears down the in-flight HTTP request and body read. The
  abort surfaces as an AgencyCancelledError that propagates out of the
  surrounding `try`.
*/
export def fetch(
  baseUrl: string,
  path: string = "",
  headers: Record<string, any> = {},
  allowedDomains: string[] = [],
  method: HttpMethod = "GET",
  body: Record<string, any> | string | null = null,
): Result {
  """
  Fetch a URL and return the response as text.

  @param baseUrl - The base URL to fetch
  @param path - Optional path appended to baseUrl
  @param headers - Custom request headers
  @param allowedDomains - Restrict fetches to these domains (empty allows all)
  @param method - The HTTP method
  @param body - Request body: a string is sent as-is, a non-string is sent as JSON
  """
  return interrupt std::http::fetch("Allow a ${method} request to this URL?", {
    baseUrl: baseUrl,
    path: path,
    method: method
  })
  return try _fetch(baseUrl, path, headers, allowedDomains, method, body)
}

/**
  On abort, Agency tears down the in-flight HTTP request and body read. The
  abort surfaces as an AgencyCancelledError that propagates out of the
  surrounding `try`.
*/
export def fetchJSON(
  baseUrl: string,
  path: string = "",
  headers: Record<string, any> = {},
  allowedDomains: string[] = [],
  method: HttpMethod = "GET",
  body: Record<string, any> | string | null = null,
): Result {
  """
  Fetch a URL and return the response parsed as JSON.

  @param baseUrl - The base URL to fetch
  @param path - Optional path appended to baseUrl
  @param headers - Custom request headers
  @param allowedDomains - Restrict fetches to these domains (empty allows all)
  @param method - The HTTP method
  @param body - Request body: a string is sent as-is, a non-string is sent as JSON
  """
  return interrupt std::http::fetchJSON("Allow a ${method} request to this URL and parse the response as JSON?", {
    baseUrl: baseUrl,
    path: path,
    method: method
  })
  return try _fetchJSON(baseUrl, path, headers, allowedDomains, method, body)
}

/**
  On abort, Agency tears down the in-flight HTTP request and body read. The
  abort surfaces as an AgencyCancelledError that propagates out of the
  surrounding `try`.
*/
export def fetchMarkdown(baseUrl: string, path: string = "", headers: Record<string, any> = {}, allowedDomains: string[] = [], method: HttpMethod = "GET", body: Record<string, any> | string | null = null): Result {
  """
  Fetch a URL and return the body as readable markdown when the response is HTML, or as plain text otherwise. Good for extracting page content for an LLM. Fails on network errors, domain violations, or if the response body exceeds 10 MB.

  @param baseUrl - The base URL to fetch
  @param path - Optional path appended to baseUrl
  @param headers - Custom request headers
  @param allowedDomains - Restrict fetches to these domains (empty allows all)
  @param method - The HTTP method
  @param body - Request body: a string is sent as-is, a non-string is sent as JSON
  """
  return interrupt std::http::fetchMarkdown("Allow a ${method} request to this URL?", {
    baseUrl: baseUrl,
    path: path,
    method: method
  })
  return try _fetchMarkdown(baseUrl, path, headers, allowedDomains, method, body)
}
