// 真实传输层:基于 moonbitlang/async/http 的 FetchFn 实现。
//
// - 30 秒整体超时(@async.with_timeout_opt)
// - 失败(协议错误/超时/解码错误)统一折叠为 status=0 + error
// - 重定向跟随行为取决于底层客户端(js 后端经 Node fetch 自动跟随)
// - 显式发送 User-Agent:robots.txt 的组匹配依赖它

///|
const HTTP_TIMEOUT_MS : Int32 = 30_000

///|
/// FetchFn 的默认实现。
pub async fn http_fetch(url : String, user_agent : String) -> FetchOutcome {
  let headers : Map[@http.CaseInsensitiveString, String] = Map([], capacity=4)
  let _ = headers.set(@http.CaseInsensitiveString("user-agent"), user_agent)
  let task : async () -> FetchOutcome = async fn() -> FetchOutcome {
    let (resp, data) = @http.get(url, headers~)
    let body = data.text()
    { status: resp.code, body, error: None, }
  }
  match @async.with_timeout_opt(HTTP_TIMEOUT_MS, task) {
    Some(outcome) => outcome
    None => { status: 0, body: "", error: Some("timeout after 30s"), }
  }
}