// ============================================================================
// 三条链的驱动:顺序与错误流转。全部是包私有函数,
// 只被 `pipeline.mbt` 的 `Client::request`(与 `stream_entry.mbt` 的
// 请求侧正常链)调用。
// ============================================================================

///|
/// 跑请求侧正常链:**后注册先跑**(LIFO,与 axios 一致),每个拦截器拿到的都是
/// 上一个(更晚注册的)拦截器交出来的配置。
///
/// 拦截器抛错就原样抛(`raise HttpError`):被拦下意味着「这次请求不发了」,
/// 这个错误交给谁收口由调用方决定——`Client::request` 把它和派发阶段的失败
/// 一起收进 `stage`,再交给请求侧错误处理器;两个流式入口没有错误处理器,
/// 直接抛给调用方。不要在链内部先包成 `Result`:那只是让同一次失败多绕一层。
async fn Interceptors::run_request(
  self : Interceptors,
  config : Config,
) -> Config raise HttpError {
  let mut current = config
  for i = self.requests.length() - 1; i >= 0; i = i - 1 {
    // 字段里的函数值要先绑到局部变量再调:`pair.on_fulfilled(x)` 会被当成
    // 「在 `RequestPair` 上找一个叫 on_fulfilled 的方法」。
    let on_request = self.requests[i].on_fulfilled
    // 抛错即中止:后面的(更早注册的)拦截器不再跑,错误直接出链。
    current = on_request(current)
  }
  current
}

///|
/// 跑请求侧错误链:**后注册先跑**(与请求侧正常链同向,理由见
/// `docs/11-interceptors.md`)。
///
/// 每个错误处理器拿到当前错误:返回 `Response` 表示就地救回,立刻结束(这次请求
/// 的结果就是它);`raise error` 表示不处理,把(可能是自己新造的)错误交给更早
/// 注册的处理器。全部没接住就抛最后那个错误——与 axios 的 promise 链一样,
/// 错误处理器可以「换一个错误继续往外传」。
async fn Interceptors::run_request_errors(
  self : Interceptors,
  error : HttpError,
) -> Response raise HttpError {
  let mut current = error
  let mut rescued : Response? = None
  for i = self.requests.length() - 1; i >= 0; i = i - 1 {
    // 救回来之后剩下的处理器不再打扰:链的意义就是「谁接住就谁说了算」。
    if rescued is None {
      let on_rejected = self.requests[i].on_rejected
      let outcome = Ok(on_rejected(current)) catch { e => Err(e) }
      match outcome {
        Ok(response) => rescued = Some(response)
        Err(next) => current = next
      }
    }
  }
  match rescued {
    Some(response) => response
    None => raise current
  }
}

///|
/// 跑响应侧链:**先注册先跑**(FIFO,与 axios 一致)。
///
/// 进来的 `outcome` 只有两种来源:通过校验的响应,或**状态码没通过校验**的错误
/// (请求阶段的失败不进这里,它们走 `run_request_errors`)。与 axios 的 promise
/// 链同构:`Ok` 走正常处理器、`Err` 走错误处理器;处理器自己抛出的错误落到
/// **更晚注册**的错误处理器手里,没人接住就抛给调用方。
/// 所以「状态码失败的重试」写在哪里是有讲究的:越早注册的错误处理器越先看到错误。
async fn Interceptors::run_response(
  self : Interceptors,
  outcome : Result[Response, HttpError],
) -> Response raise HttpError {
  let mut state = outcome
  for pair in self.responses {
    let on_fulfilled = pair.on_fulfilled
    let on_rejected = pair.on_rejected
    state = match state {
      Ok(response) => Ok(on_fulfilled(response)) catch { error => Err(error) }
      Err(error) => Ok(on_rejected(error)) catch { error => Err(error) }
    }
  }
  match state {
    Ok(response) => response
    Err(error) => raise error
  }
}