///|
fn trim_end_slashes(input : String) -> String {
  let mut output = input
  while output.has_suffix("/") {
    output = output[:output.length() - 1].to_owned()
  }
  output
}

///|
fn trim_start_slashes(input : String) -> String {
  let mut output = input
  while output.has_prefix("/") {
    output = output[1:].to_owned()
  }
  output
}

///|
fn normalize_gemini_model_id(model : String) -> String {
  let trimmed = if model.has_prefix("/") { model[1:].to_owned() } else { model }
  if trimmed.has_prefix("models/") {
    trimmed["models/".length():].to_owned()
  } else {
    trimmed
  }
}

///|
fn resolve_gemini_native_url(
  base_url : String,
  endpoint : String,
  is_full_url : Bool,
) -> String {
  if !is_full_url || should_normalize_gemini_full_url(base_url) {
    build_gemini_native_url(base_url, endpoint)
  } else {
    let base_url = trim_end_slashes(trim_url_fragment(base_url))
    let (base_without_query, base_query) = split_query(base_url)
    let (_, endpoint_query) = split_query(endpoint)
    match merge_queries(base_query, endpoint_query) {
      Some(query) => "\{base_without_query}?\{query}"
      None => base_without_query
    }
  }
}

///|
fn build_gemini_native_url(base_url : String, endpoint : String) -> String {
  let base_url = trim_end_slashes(trim_url_fragment(base_url))
  let (base_without_query, base_query) = split_query(base_url)
  let (endpoint_without_query, endpoint_query) = split_query(endpoint)
  let endpoint_path = "/\{trim_start_slashes(endpoint_without_query)}"
  let (origin, raw_path) = split_origin_and_path(base_without_query)
  let prefix_path = normalize_gemini_base_path(raw_path)
  let url = if prefix_path.is_empty() {
    "\{origin}\{endpoint_path}"
  } else {
    "\{origin}\{prefix_path}\{endpoint_path}"
  }
  match merge_queries(base_query, endpoint_query) {
    Some(query) => "\{url}?\{query}"
    None => url
  }
}

///|
fn should_normalize_gemini_full_url(base_url : String) -> Bool {
  let base_url = trim_end_slashes(trim_url_fragment(base_url))
  let (base_without_query, _) = split_query(base_url)
  let (origin, path) = split_origin_and_path(base_without_query)
  if path.is_empty() || path == "/" {
    return true
  }
  let path = trim_end_slashes(path)
  let on_google_host = is_google_gemini_host(extract_host(origin))
  if matches_vertex_ai_publisher_model_path(path) {
    return false
  }
  if matches_structured_gemini_models_path(path) ||
    path.has_suffix("/v1beta/openai/chat/completions") ||
    path.has_suffix("/v1beta/openai/responses") ||
    path.has_suffix("/openai/chat/completions") ||
    path.has_suffix("/openai/responses") ||
    path.has_suffix("/v1/openai/chat/completions") ||
    path.has_suffix("/v1/openai/responses") {
    return true
  }
  on_google_host &&
  (
    path.has_suffix("/v1beta") ||
    path.has_suffix("/v1beta/models") ||
    path.has_suffix("/v1beta/openai") ||
    path.has_suffix("/v1") ||
    path.has_suffix("/v1/models") ||
    path.has_suffix("/models") ||
    path.has_suffix("/v1/openai") ||
    path.has_suffix("/openai")
  )
}

///|
fn trim_url_fragment(input : String) -> String {
  match input.find("#") {
    Some(index) => input[:index].to_owned()
    None => input
  }
}

///|
fn split_query(input : String) -> (String, String?) {
  match input.find("?") {
    Some(index) =>
      (input[:index].to_owned(), Some(input[index + 1:].to_owned()))
    None => (input, None)
  }
}

///|
fn split_origin_and_path(base_url : String) -> (String, String) {
  match base_url.find("://") {
    None => (base_url, "")
    Some(scheme_index) => {
      let authority_start = scheme_index + 3
      let rest = base_url[authority_start:]
      match rest.find("/") {
        None => (base_url, "")
        Some(path_start_rel) => {
          let path_start = authority_start + path_start_rel
          (base_url[:path_start].to_owned(), base_url[path_start:].to_owned())
        }
      }
    }
  }
}

///|
fn normalize_gemini_base_path(path : String) -> String {
  let path = trim_end_slashes(path)
  if path.is_empty() || path == "/" {
    return ""
  }
  for marker in ["/v1beta/models/", "/v1/models/", "/models/"] {
    if path.find(marker) is Some(index) {
      return normalize_prefix(path[:index].to_owned())
    }
  }
  for
    suffix in [
      "/v1beta/openai/chat/completions", "/v1/openai/chat/completions", "/openai/chat/completions",
      "/v1beta/openai/responses", "/v1/openai/responses", "/openai/responses", "/v1beta/openai",
      "/v1/openai", "/openai", "/v1beta/models", "/v1/models", "/models", "/v1beta",
      "/v1",
    ] {
    if path == suffix {
      return ""
    }
    if path.has_suffix(suffix) {
      return normalize_prefix(path[:path.length() - suffix.length()].to_owned())
    }
  }
  path
}

///|
fn normalize_prefix(prefix : String) -> String {
  let prefix = trim_end_slashes(prefix)
  if prefix.is_empty() || prefix == "/" {
    ""
  } else {
    prefix
  }
}

///|
fn extract_host(origin : String) -> String {
  let after_scheme = match origin.find("://") {
    Some(index) => origin[index + 3:]
    None => origin
  }
  let without_userinfo = match after_scheme.rev_find("@") {
    Some(index) => after_scheme[index + 1:]
    None => after_scheme
  }
  let without_port = match without_userinfo.find(":") {
    Some(index) => without_userinfo[:index]
    None => without_userinfo
  }
  trim_end_slashes(without_port.to_owned())
}

///|
fn is_google_gemini_host(host : String) -> Bool {
  if host.is_empty() {
    return false
  }
  let host_lower = host.to_lower()
  host_lower == "generativelanguage.googleapis.com" ||
  host_lower == "aiplatform.googleapis.com" ||
  host_lower.has_suffix("-aiplatform.googleapis.com")
}

///|
fn matches_structured_gemini_models_path(path : String) -> Bool {
  let mut cursor = path
  while cursor.find("/models/") is Some(index) {
    let after = cursor[index + "/models/".length():]
    if after.contains(":generateContent") ||
      after.contains(":streamGenerateContent") {
      return true
    }
    cursor = after.to_owned()
  }
  false
}

///|
fn matches_vertex_ai_publisher_model_path(path : String) -> Bool {
  match (path.find("/projects/"), path.find("/publishers/google/models/")) {
    (Some(projects_index), Some(publisher_models_index)) => {
      if projects_index >= publisher_models_index ||
        !path[projects_index:publisher_models_index].contains("/locations/") {
        return false
      }
      let after_model = path[publisher_models_index +
        "/publishers/google/models/".length():]
      after_model.contains(":generateContent") ||
      after_model.contains(":streamGenerateContent")
    }
    _ => false
  }
}

///|
fn merge_queries(base_query : String?, endpoint_query : String?) -> String? {
  let parts : Array[String] = []
  match base_query {
    Some(query) =>
      for part in query.split("&") {
        if !part.is_empty() {
          parts.push(part.to_owned())
        }
      }
    None => ()
  }
  match endpoint_query {
    Some(query) =>
      for part in query.split("&") {
        if !part.is_empty() {
          parts.push(part.to_owned())
        }
      }
    None => ()
  }
  if parts.is_empty() {
    None
  } else {
    Some(parts.join("&"))
  }
}