///| Resource Owner Password Credentials Grant Implementation (RFC 6749 Section 4.3)

///|
/// WARNING: Resource Owner Password Credentials Grant is deprecated
/// and should only be used for legacy systems. Consider using
/// Authorization Code Grant with PKCE instead.
///
/// PasswordRequest represents an OAuth2 password credentials request
/// Used when the resource owner has a trust relationship with the client
pub struct PasswordRequest {
  token_url : TokenUrl
  client_id : ClientId
  client_secret : ClientSecret?
  username : String
  password : String
  scope : Array[Scope]
  grant_type : String
} derive(Show)

///|
/// Create a new PasswordRequest
/// WARNING: This grant type is deprecated. Use Authorization Code Flow with PKCE instead.
pub fn PasswordRequest::new(
  token_url : TokenUrl,
  client_id : ClientId,
  client_secret : ClientSecret?,
  username : String,
  password : String,
  scope : Array[Scope],
) -> PasswordRequest {
  {
    token_url,
    client_id,
    client_secret,
    username,
    password,
    scope,
    grant_type: "password",
  }
}

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

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

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

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

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

  // client_secret (optional)
  match self.client_secret {
    Some(secret) => params["client_secret"] = secret.to_string()
    None => ()
  }

  // 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
/// Returns None if client_secret is not provided
pub fn PasswordRequest::get_auth_header(self : PasswordRequest) -> String? {
  match self.client_secret {
    Some(secret) => Some(build_basic_auth_header(self.client_id, secret))
    None => None
  }
}

///|
/// Execute the password credentials request using HTTP client
/// Returns TokenResponse on success, OAuth2Error on failure
/// WARNING: This grant type is deprecated and should only be used for legacy systems.
pub async fn PasswordRequest::execute(
  self : PasswordRequest,
  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 if client_secret is provided
  // match self.get_auth_header() {
  //   Some(auth) => headers["Authorization"] = auth
  //   None => ()
  // }

  // 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)
}