///|
fn moongate_security_handler(
  next : @httpx.Handler,
  control : ControlPlaneAuth,
  configured_host : String,
  port : Int,
) -> @httpx.Handler {
  (r, w) => {
    if !moongate_request_authority_allowed(r.headers, configured_host, port) {
      moongate_write_security_error(w)
      return
    }
    let path = r.path.to_owned().split("?").head().unwrap_or("").to_owned()
    if path == "/control/bootstrap" {
      if r.method_ != Get ||
        !moongate_control_bootstrap_allowed(r.headers, configured_host, port) {
        moongate_write_security_error(w)
        return
      }
      control.write_bootstrap(w)
      return
    }
    if moongate_route_requires_control(r.method_, path) &&
      !control.authorized(r.headers) {
      moongate_write_control_auth_error(w)
      return
    }
    if moongate_static_route(r.method_, path) {
      w.header().set("Cache-Control", "no-store")
    }
    next(r, w)
  }
}

///|
fn moongate_control_bootstrap_allowed(
  headers : Map[String, String],
  configured_host : String,
  port : Int,
) -> Bool {
  match headers.get("origin") {
    Some(origin) => {
      if !moongate_origin_allowed(origin, configured_host, port) {
        return false
      }
      match headers.get("sec-fetch-site") {
        Some(site) => site == "same-origin"
        None => true
      }
    }
    None => headers.get("sec-fetch-site") == Some("same-origin")
  }
}

///|
fn moongate_route_requires_control(
  method_ : @httpx.Method,
  path : String,
) -> Bool {
  if moongate_inference_route(method_, path) ||
    moongate_public_route(method_, path) ||
    moongate_static_route(method_, path) {
    return false
  }
  true
}

///|
fn moongate_inference_route(method_ : @httpx.Method, path : String) -> Bool {
  match method_ {
    Post =>
      path == "/v1/messages" ||
      path == "/claude-desktop/v1/messages" ||
      path == "/v1/chat/completions" ||
      path == "/openclaw/v1/chat/completions" ||
      path == "/v1/responses" ||
      path == "/v1/responses/compact" ||
      path.has_prefix("/gemini/v1/") ||
      path.has_prefix("/gemini/v1beta/")
    Get =>
      path == "/v1/models" ||
      path == "/openclaw/v1/models" ||
      path == "/claude-desktop/v1/models" ||
      path.has_prefix("/gemini/v1/") ||
      path.has_prefix("/gemini/v1beta/")
    _ => false
  }
}

///|
fn moongate_public_route(method_ : @httpx.Method, path : String) -> Bool {
  method_ == Get &&
  (
    path == "/health" ||
    path == "/status" ||
    path == "/stats" ||
    path == "/metrics" ||
    path == "/suite/manifest" ||
    path == "/suite/status" ||
    path == "/suite/moonclaw-providers"
  )
}

///|
fn moongate_static_route(method_ : @httpx.Method, path : String) -> Bool {
  method_ == Get &&
  (
    path == "/" ||
    path == "/ui/rabbita" ||
    path == "/participant/register" ||
    path == "/favicon.ico" ||
    path.has_prefix("/assets/")
  )
}

///|
fn moongate_request_authority_allowed(
  headers : Map[String, String],
  configured_host : String,
  port : Int,
) -> Bool {
  guard headers.get("host") is Some(host_header) else { return false }
  guard moongate_parse_authority(host_header) is Some(authority) else {
    return false
  }
  if !moongate_host_allowed(authority.host, configured_host) ||
    !moongate_request_port_allowed(authority.host, authority.port, port) {
    return false
  }
  match headers.get("origin") {
    None => true
    Some(origin) => moongate_origin_allowed(origin, configured_host, port)
  }
}

///|
fn moongate_request_port_allowed(
  host : String,
  actual : Int?,
  expected : Int,
) -> Bool {
  moongate_port_allowed(actual, expected) ||
  (actual is None && moongate_loopback_host(host))
}

///|
fn moongate_loopback_host(host : String) -> Bool {
  let normalized = host.trim().to_lower()
  normalized == "localhost" || normalized == "127.0.0.1" || normalized == "::1"
}

///|
fn moongate_parse_authority(authority : String) -> @url.Url? {
  let value = authority.trim()
  if value.is_empty() {
    return None
  }
  Some(@url.parse("http://\{value}")) catch {
    _ => None
  }
}

///|
fn moongate_origin_allowed(
  origin : String,
  configured_host : String,
  port : Int,
) -> Bool {
  let value = origin.trim().to_owned()
  if value.is_empty() || value == "null" {
    return false
  }
  let parsed = @url.parse(value) catch { _ => return false }
  moongate_host_allowed(parsed.host, configured_host) &&
  moongate_port_allowed(parsed.port, port)
}

///|
fn moongate_host_allowed(host : String, configured_host : String) -> Bool {
  let normalized = host.trim().to_lower()
  let configured = configured_host.trim().to_lower()
  normalized == configured ||
  normalized == "localhost" ||
  normalized == "127.0.0.1" ||
  normalized == "::1"
}

///|
fn moongate_port_allowed(actual : Int?, expected : Int) -> Bool {
  match actual {
    Some(port) => port == expected
    None => expected == 80 || expected == 443
  }
}

///|
async fn moongate_write_security_error(w : @httpx.ResponseWriter) -> Unit {
  moongate_write_json_error(
    w,
    @status.Forbidden,
    "moongate_untrusted_request_authority",
    "Host or Origin is not trusted by MoonGate",
  )
}

///|
async fn moongate_write_control_auth_error(w : @httpx.ResponseWriter) -> Unit {
  moongate_write_json_error(
    w,
    @status.Unauthorized,
    "moongate_control_auth_required",
    "A valid MoonGate control token is required",
  )
}

///|
async fn moongate_write_json_error(
  w : @httpx.ResponseWriter,
  status_code : Int,
  code : String,
  message : String,
) -> Unit {
  w.header().set("Content-Type", "application/json")
  w.header().set("Cache-Control", "no-store")
  w.write_header(status_code)
  w.write(
    {
      "error": { "code": Json::string(code), "message": Json::string(message) }.to_json(),
    }
    .to_json()
    .stringify(),
  )
  w.flush()
}