// `If` 请求头渲染:锁令牌(无标签列表)与通用条件列表(RFC 4918 §10.4)。
// 只负责拼字符串与本地校验,不发请求;落到请求头上见 client.mbt。
// 单独成文件以遵守单文件行数上限(AGENTS.md RL-04)。

///|
/// 归一化锁令牌为 `Lock-Token` 头形态:`<令牌>`。
/// 令牌可能自带尖括号(`Lock-Token` 响应头就是这种形状),也可能不带,
/// 统一只包一层,不会出现 `<<令牌>>`。
fn lock_token_uri(token : String) -> String {
  "<" + @types.normalize_lock_token(token) + ">"
}

///|
/// `If` 头里的锁令牌形态:`(<令牌>)`(RFC 4918 §10.4.1 的无标签列表)。
fn lock_token_if_value(token : String) -> String {
  "(" + lock_token_uri(token) + ")"
}

///|
/// 渲染单个 `If` 条件:可选的 `Not ` 前缀 + 状态令牌或实体标签
/// (RFC 4918 §10.4.2 的 `Condition`)。
fn render_if_condition(
  condition : @types.IfCondition,
  operation~ : String,
) -> String raise @types.WebdavError {
  let prefix = if condition.negated { "Not " } else { "" }
  match condition.kind {
    @types.IfConditionKind::StateToken => {
      let token = @types.normalize_lock_token(condition.value)
      if token == "" {
        // 空状态令牌既不合法也无从匹配,宁可本地报错也不发出去。
        raise @types.WebdavError::api(
          status=400,
          operation~,
          message="If 条件里的锁令牌不能为空",
        )
      }
      prefix + "<" + token + ">"
    }
    @types.IfConditionKind::EntityTag => prefix + "[" + condition.value + "]"
  }
}

///|
/// 渲染一个 `If` 列表:`(条件 条件 ...)`,带资源标签时前缀 `<标签>`。
/// 列表内多个条件是合取关系;资源标签只对它后面这一个列表生效。
fn render_if_list(
  list : @types.IfList,
  operation~ : String,
) -> String raise @types.WebdavError {
  if list.conditions.length() == 0 {
    raise @types.WebdavError::api(
      status=400,
      operation~,
      message="If 列表至少要有一个条件",
    )
  }
  let items : Array[String] = []
  for condition in list.conditions {
    items.push(render_if_condition(condition, operation~))
  }
  let body = "(" + items.join(" ") + ")"
  match list.resource_tag {
    Some(tag) => {
      if tag == "" {
        raise @types.WebdavError::api(
          status=400,
          operation~,
          message="If 列表的资源标签不能为空",
        )
      }
      "<" + tag + "> " + body
    }
    None => body
  }
}

///|
/// 渲染整个 `If` 头(不含头名):通用条件列表在前,锁令牌列表在后,
/// 空格连接;没有可渲染的内容时返回空串。
///
/// 无标签列表与带标签列表不能出现在同一个 `If` 头里(RFC 4918 §10.4.2),
/// 混用时本地抛 `Api` 400,不浪费一次往返;带标签模式下锁令牌渲染成
/// ` (<令牌>)` 这个独立 production。
fn render_if_header(
  conditions : @types.Conditions,
  url~ : String,
  operation~ : String,
) -> String raise @types.WebdavError {
  let untagged : Array[String] = []
  let tagged : Array[String] = []
  for list in conditions.if_lists {
    let rendered = render_if_list(list, operation~)
    match list.resource_tag {
      Some(_) => tagged.push(rendered)
      None => untagged.push(rendered)
    }
  }
  let token = match conditions.lock_token {
    Some(raw) => @types.normalize_lock_token(raw)
    None => ""
  }
  if untagged.length() > 0 && tagged.length() > 0 {
    raise @types.WebdavError::api(
      status=400,
      operation~,
      message="If 头的无标签列表与带标签列表不能混用",
    )
  }
  if tagged.length() > 0 {
    if token != "" {
      tagged.push("<" + url + "> (" + lock_token_uri(token) + ")")
    }
    tagged.join(" ")
  } else {
    if token != "" {
      untagged.push("(" + lock_token_uri(token) + ")")
    }
    untagged.join(" ")
  }
}