///|
/// Standard JWT claim keys (RFC 7519 ยง4).
pub let claim_iss : String = "iss"

///|
pub let claim_sub : String = "sub"

///|
pub let claim_aud : String = "aud"

///|
pub let claim_exp : String = "exp"

///|
pub let claim_nbf : String = "nbf"

///|
pub let claim_iat : String = "iat"

///|
pub let claim_jti : String = "jti"

///|
/// A builder for constructing JWT claims as a JSON object.
///
/// Standard claims (iss, sub, aud, exp, nbf, iat, jti) have dedicated
/// methods; custom claims can be added with [ClaimsBuilder::set].
pub(all) struct ClaimsBuilder {
  mut claims : Map[String, Json]
}

///|
/// Create a new empty claims builder.
pub fn ClaimsBuilder::new() -> ClaimsBuilder {
  { claims: Map([]) }
}

///|
/// Set the issuer claim (who issued the token).
pub fn ClaimsBuilder::issuer(
  self : ClaimsBuilder,
  iss : String,
) -> ClaimsBuilder {
  self.claims[claim_iss] = Json::string(iss)
  self
}

///|
/// Set the subject claim (who the token is about).
pub fn ClaimsBuilder::subject(
  self : ClaimsBuilder,
  sub : String,
) -> ClaimsBuilder {
  self.claims[claim_sub] = Json::string(sub)
  self
}

///|
/// Set the audience claim (intended recipient).
pub fn ClaimsBuilder::audience(
  self : ClaimsBuilder,
  aud : String,
) -> ClaimsBuilder {
  self.claims[claim_aud] = Json::string(aud)
  self
}

///|
/// Set the expiration time claim (NumericDate: seconds since epoch).
pub fn ClaimsBuilder::expires_at(
  self : ClaimsBuilder,
  exp : Int,
) -> ClaimsBuilder {
  self.claims[claim_exp] = Json::number(exp.to_double())
  self
}

///|
/// Set the not-before claim (token not valid before this time).
pub fn ClaimsBuilder::not_before(
  self : ClaimsBuilder,
  nbf : Int,
) -> ClaimsBuilder {
  self.claims[claim_nbf] = Json::number(nbf.to_double())
  self
}

///|
/// Set the issued-at claim (when the token was issued).
pub fn ClaimsBuilder::issued_at(
  self : ClaimsBuilder,
  iat : Int,
) -> ClaimsBuilder {
  self.claims[claim_iat] = Json::number(iat.to_double())
  self
}

///|
/// Set the JWT ID claim (unique identifier for the token).
pub fn ClaimsBuilder::jwt_id(
  self : ClaimsBuilder,
  jti : String,
) -> ClaimsBuilder {
  self.claims[claim_jti] = Json::string(jti)
  self
}

///|
/// Set a custom string claim.
pub fn ClaimsBuilder::set_string(
  self : ClaimsBuilder,
  key : String,
  value : String,
) -> ClaimsBuilder {
  self.claims[key] = Json::string(value)
  self
}

///|
/// Set a custom integer claim.
pub fn ClaimsBuilder::set_int(
  self : ClaimsBuilder,
  key : String,
  value : Int,
) -> ClaimsBuilder {
  self.claims[key] = Json::number(value.to_double())
  self
}

///|
/// Set a custom boolean claim.
pub fn ClaimsBuilder::set_bool(
  self : ClaimsBuilder,
  key : String,
  value : Bool,
) -> ClaimsBuilder {
  self.claims[key] = Json::boolean(value)
  self
}

///|
/// Set a custom claim from a raw JSON value.
pub fn ClaimsBuilder::set(
  self : ClaimsBuilder,
  key : String,
  value : Json,
) -> ClaimsBuilder {
  self.claims[key] = value
  self
}

///|
/// Remove a claim by key.
pub fn ClaimsBuilder::remove(
  self : ClaimsBuilder,
  key : String,
) -> ClaimsBuilder {
  self.claims.remove(key)
  self
}

///|
/// Check if a claim exists.
pub fn ClaimsBuilder::contains(self : ClaimsBuilder, key : String) -> Bool {
  self.claims.contains(key)
}

///|
/// Get a claim value.
pub fn ClaimsBuilder::get(self : ClaimsBuilder, key : String) -> Json? {
  match self.claims.get(key) {
    Some(v) => Some(v)
    None => None
  }
}

///|
/// Build the claims as a JSON string.
pub fn ClaimsBuilder::to_json_string(self : ClaimsBuilder) -> String {
  Json::object(self.claims).stringify()
}

///|
/// Build the claims as a JSON value.
pub fn ClaimsBuilder::to_json(self : ClaimsBuilder) -> Json {
  Json::object(self.claims)
}