// 响应状态码判定:期望状态码集合、失败时的中文注解与响应体摘要、
// 207 Multi-Status 的失败条目提取。与具体操作解耦,单独成文件(RL-04)。

///|
/// 常见 WebDAV 状态码的中文注解(用于 Api 错误消息)。
fn status_message(status : Int32) -> String {
  match status {
    200 => "成功"
    201 => "已创建"
    204 => "成功(无响应体)"
    206 => "部分内容(Range)"
    207 => "Multi-Status"
    301 | 302 | 307 | 308 => "重定向"
    400 => "请求不合法"
    401 => "未认证(检查用户名 / 密码)"
    403 => "无权限"
    404 => "资源不存在"
    405 => "方法不允许(目标已存在或服务器不支持该操作)"
    409 => "冲突(父目录不存在?)"
    412 => "前置条件失败(目标已存在且不允许覆盖?)"
    416 => "请求区间不满足(Range Not Satisfiable)"
    423 => "资源被锁定"
    502 | 504 => "网关错误"
    507 => "存储空间不足"
    _ => "服务端返回异常状态"
  }
}

///|
/// 从响应体里取一段摘要(最多 200 字符)拼进错误消息;
/// 响应体为空时返回空串。部分服务端用响应体说明失败原因。
fn body_hint(response : @moonhttp.Response) -> String {
  let text = response.text().trim()
  if text.length() == 0 {
    ""
  } else if text.length() > 200 {
    "(响应体:" + text[:200].to_owned() + "…)"
  } else {
    "(响应体:" + text.to_owned() + ")"
  }
}

///|
/// 校验响应状态码:不在 ok 集合内则抛 `Api` 错误。
fn check_status(
  response : @moonhttp.Response,
  operation~ : String,
  ok~ : Array[Int32],
) -> @moonhttp.Response raise @types.WebdavError {
  if ok.contains(response.status) {
    response
  } else {
    raise @types.WebdavError::api(
      status=response.status,
      operation~,
      message=status_message(response.status) + body_hint(response),
    )
  }
}

///|
/// 从 207 响应里提取失败条目:`response` 级状态码非 2xx 的资源。
/// 没有 `` 的响应(纯 PROPFIND 形态)视为无失败。
fn failures_from_multistatus(
  response : @moonhttp.Response,
) -> Array[@types.ResourceFailure] raise @types.WebdavError {
  let resources = @xmlutil.parse_multistatus(response.text()) catch {
    error => raise @types.WebdavError::xml(error)
  }
  let failures : Array[@types.ResourceFailure] = []
  for resource in resources {
    match resource.status {
      Some(status) =>
        if status < 200 || status >= 300 {
          failures.push({
            href: resource.href,
            status,
            message: status_message(status),
          })
        }
      None => ()
    }
  }
  failures
}

///|
/// 允许 207 的状态校验:先按 ok 集合放行,若响应是 207,则从响应体里
/// 找失败条目——有失败抛 `Partial`,全是 2xx 视为整体成功。
fn check_status_allow_partial(
  response : @moonhttp.Response,
  operation~ : String,
  ok~ : Array[Int32],
) -> Unit raise @types.WebdavError {
  let checked = check_status(response, operation~, ok~)
  if checked.status == 207 {
    let failures = failures_from_multistatus(checked)
    if failures.length() > 0 {
      raise @types.WebdavError::partial(operation~, failures~)
    }
  }
}