///| Client Credentials Grant Implementation (RFC 6749 Section 4.4)

///|
/// ClientCredentialsRequest represents an OAuth2 client credentials request
/// Used for machine-to-machine (M2M) authentication
pub struct ClientCredentialsRequest {
  token_url : TokenUrl
  client_id : ClientId
  client_secret : ClientSecret
  scope : Array[Scope]
  grant_type : String
} derive(Show)

///|
/// Create a new ClientCredentialsRequest
pub fn ClientCredentialsRequest::new(
  token_url : TokenUrl,
  client_id : ClientId,
  client_secret : ClientSecret,
  scope : Array[Scope],
) -> ClientCredentialsRequest {
  {
    token_url,
    client_id,
    client_secret,
    scope,
    grant_type: "client_credentials",
  }
}

///|
/// Build the request body for client credentials request
/// Returns application/x-www-form-urlencoded format
pub fn ClientCredentialsRequest::build_request_body(
  self : ClientCredentialsRequest,
) -> String {
  let params : Map[String, String] = {}

  // grant_type (required)
  params["grant_type"] = self.grant_type

  // client_id (required)
  params["client_id"] = self.client_id.to_string()

  // client_secret (required)
  params["client_secret"] = self.client_secret.to_string()

  // scope (optional)
  if self.scope.length() > 0 {
    let scope_str = build_scope_string(self.scope)
    params["scope"] = scope_str
  }

  build_form_urlencoded_body(params)
}

///|
/// Get authorization header for Basic authentication
pub fn ClientCredentialsRequest::get_auth_header(
  self : ClientCredentialsRequest,
) -> String {
  build_basic_auth_header(self.client_id, self.client_secret)
}

///|
/// Execute the client credentials request using HTTP client
/// Returns TokenResponse on success, OAuth2Error on failure
pub async fn ClientCredentialsRequest::execute(
  self : ClientCredentialsRequest,
  http_client : OAuth2HttpClient,
) -> Result[TokenResponse, OAuth2Error] {
  // Build request body
  let body = self.build_request_body()

  // Set up headers
  let headers : HttpHeaders = {}
  headers["Content-Type"] = "application/x-www-form-urlencoded"
  // Optional: Use Basic authentication
  // headers["Authorization"] = self.get_auth_header()

  // Send POST request
  let response = match
    http_client.post(self.token_url.to_string(), headers, body) {
    Ok(resp) => resp
    Err(err) => return Err(err)
  }

  // Check if response is successful (2xx status code)
  if response.is_error() {
    // Parse OAuth2 error from response body
    let error = parse_oauth2_error(response.body)
    return Err(error)
  }

  // Parse token response
  parse_token_response(response.body)
}