// 移植自 github.com/milvus-io/milvus client/internal/merr (Apache-2.0)
// Copyright (c) LF AI & Data Foundation

///|
/// 包装函数族,对应上游 `merr` 的 `WrapErr*` 与 `withDetails`。
///
/// 共同语义:**保留 base 的 code / legacy_code / retriable / input,
/// 只改写 message 与 detail**。一旦携带了 code 身份,就能用 `same_code`
/// 或 `code()` 重新识别出来 —— 这就是 Go 版 `errors.Is` 在本项目里的等价物。
///
/// `messages` 为上下文链,按 `a->b: ` 拼接,与上游一致。
fn with_context(
  base : MerError,
  message : String,
  messages : Array[String],
) -> MerError {
  let composed = if messages.length() == 0 {
    message
  } else {
    messages.join("->") + ": " + message
  }
  match base {
    RpcError(code~, legacy_code~, retriable~, input~, ..) =>
      RpcError(
        code~,
        legacy_code~,
        message=redact(composed),
        detail=redact(composed),
        retriable~,
        input~,
      )
  }
}

///|
/// 取 base 的 message,用于拼 `xxx[field=value]` 形式的细节。
fn base_message(base : MerError) -> String {
  match base {
    RpcError(message~, ..) => message
  }
}

///|
fn with_details(base : MerError, field : String, value : String) -> MerError {
  with_context(base, base_message(base) + "[" + field + "=" + value + "]", [])
}

///|
/// `ErrServiceNotReady` 带 role / sessionID / state 的包装。
pub fn wrap_err_service_not_ready(
  role : String,
  session_id : Int64,
  state : String,
  messages? : Array[String] = [],
) -> MerError {
  let base = err_service_not_ready()
  let detail = base_message(base) +
    "[" +
    role +
    "=" +
    session_id.to_string() +
    "]: " +
    state
  with_context(base, detail, messages)
}

///|
/// `ErrServiceInternal` 带 reason 的包装。
pub fn wrap_err_service_internal(
  reason : String,
  messages? : Array[String] = [],
) -> MerError {
  let base = err_service_internal()
  with_context(base, base_message(base) + ": " + reason, messages)
}

///|
pub fn wrap_err_collection_not_found(
  collection : String,
  messages? : Array[String] = [],
) -> MerError {
  let base = err_collection_not_found()
  let out = with_details(base, "collection", collection)
  with_context(out, base_message(out), messages)
}

///|
pub fn wrap_err_collection_schema_mismatch(
  collection : String,
  messages? : Array[String] = [],
) -> MerError {
  let base = err_collection_schema_mismatch()
  let out = with_details(base, "collection", collection)
  with_context(out, base_message(out), messages)
}

///|
pub fn wrap_err_index_not_found(
  index_name : String,
  messages? : Array[String] = [],
) -> MerError {
  let base = err_index_not_found()
  let out = with_details(base, "indexName", index_name)
  with_context(out, base_message(out), messages)
}

///|
/// `ErrParameterInvalid` 带 expected / actual 的包装。
pub fn wrap_err_parameter_invalid(
  expected : String,
  actual : String,
  messages? : Array[String] = [],
) -> MerError {
  let base = err_parameter_invalid()
  let detail = base_message(base) +
    "[expected=" +
    expected +
    "][actual=" +
    actual +
    "]"
  with_context(base, detail, messages)
}

///|
/// `ErrParameterInvalid` 的自由文本包装(上游 `WrapErrParameterInvalidMsg`)。
pub fn wrap_err_parameter_invalid_msg(message : String) -> MerError {
  with_context(err_parameter_invalid(), message, [])
}

///|
/// 把任意错误文本重新归为 `ErrParameterInvalid`,只保留文本、不保留原 code
/// (上游 `WrapErrParameterInvalidErr`)。
pub fn wrap_err_parameter_invalid_err(
  err : String,
  message : String,
) -> MerError {
  with_context(err_parameter_invalid(), message + ": " + err, [])
}

///|
pub fn wrap_err_parameter_missing_msg(message : String) -> MerError {
  with_context(err_parameter_missing(), message, [])
}