# Control Center Validators
# JWT, RBAC, policies, compliance, and security validation

let constraints = import "../constraints/constraints.toml" in
let common = import "./common-validator.ncl" in
let string_val = import "./string-validator.ncl" in

{
  # Validate JWT token expiration in seconds
  ValidJwtTokenExpiration = fun expiration =>
    common.ValidRange
      constraints.control_center.jwt.token_expiration.min
      constraints.control_center.jwt.token_expiration.max
      expiration,

  # Validate JWT refresh token expiration
  ValidJwtRefreshExpiration = fun expiration =>
    common.ValidRange
      constraints.control_center.jwt.refresh_expiration.min
      constraints.control_center.jwt.refresh_expiration.max
      expiration,

  # Validate JWT issuer
  ValidJwtIssuer = fun issuer =>
    string_val.ValidIdentifier issuer,

  # Validate JWT audience
  ValidJwtAudience = fun audience =>
    string_val.ValidIdentifier audience,

  # Validate rate limiting max requests
  ValidRateLimitMaxRequests = fun requests =>
    common.ValidRange
      constraints.control_center.rate_limiting.max_requests.min
      constraints.control_center.rate_limiting.max_requests.max
      requests,

  # Validate rate limiting window in seconds
  ValidRateLimitWindow = fun window =>
    common.ValidRange
      constraints.control_center.rate_limiting.window_seconds.min
      constraints.control_center.rate_limiting.window_seconds.max
      window,

  # Validate session max duration in seconds
  ValidSessionMaxDuration = fun duration =>
    common.ValidRange
      constraints.control_center.session.max_duration.min
      constraints.control_center.session.max_duration.max
      duration,

  # Validate MFA max attempts
  ValidMfaMaxAttempts = fun attempts =>
    common.ValidRange
      constraints.control_center.mfa.max_attempts.min
      constraints.control_center.mfa.max_attempts.max
      attempts,

  # Validate audit log retention in days
  ValidAuditRetentionDays = fun days =>
    common.ValidRange
      constraints.control_center.audit.retention_days.min
      constraints.control_center.audit.retention_days.max
      days,

  # Validate role name
  ValidRoleName = fun role =>
    string_val.ValidIdentifier role,

  # Validate policy name
  ValidPolicyName = fun policy =>
    string_val.ValidIdentifier policy,

  # Validate RBAC configuration consistency
  ValidRbacConfig = fun rbac_config =>
    if rbac_config.enabled && rbac_config.default_role == "" then
      std.contract.blame_with_message
        "RBAC enabled but default_role is empty"
        rbac_config
    else if !rbac_config.enabled && rbac_config.hierarchy then
      std.contract.blame_with_message
        "RBAC hierarchy cannot be enabled when RBAC is disabled"
        rbac_config
    else
      rbac_config,

  # Validate policy cache TTL
  ValidPolicyCacheTtl = fun ttl =>
    if ttl < 1 then
      std.contract.blame_with_message "Policy cache TTL must be >= 1 second" ttl
    else if ttl > 86400 then
      std.contract.blame_with_message "Policy cache TTL must be <= 86400 seconds" ttl
    else
      ttl,

  # Validate max policies in cache
  ValidMaxPoliciesInCache = fun count =>
    if count < 10 then
      std.contract.blame_with_message "Max policies must be >= 10" count
    else if count > 100000 then
      std.contract.blame_with_message "Max policies must be <= 100000" count
    else
      count,

  # Validate max policy versions
  ValidMaxPolicyVersions = fun count =>
    if count < 1 then
      std.contract.blame_with_message "Max policy versions must be >= 1" count
    else if count > 100 then
      std.contract.blame_with_message "Max policy versions must be <= 100" count
    else
      count,

  # Validate data retention years for compliance
  ValidDataRetentionYears = fun years =>
    if years < 1 then
      std.contract.blame_with_message "Data retention must be >= 1 year" years
    else if years > 10 then
      std.contract.blame_with_message "Data retention must be <= 10 years" years
    else
      years,

  # Validate LDAP configuration completeness
  ValidLdapConfig = fun ldap_config =>
    if ldap_config.enabled then
      if ldap_config.server_url == null || ldap_config.server_url == "" then
        std.contract.blame_with_message
          "LDAP enabled but server_url is empty"
          ldap_config
      else
        ldap_config
    else
      ldap_config,

  # Validate compliance framework selection
  ValidComplianceFramework = fun framework =>
    let valid_frameworks = ['soc2, 'hipaa, 'pci_dss, 'gdpr] in
    common.ValidEnum valid_frameworks framework,
}
