# String Validators
# Workspace names, identifiers, and other string validations

{
  # Validate workspace name (alphanumeric, hyphen, underscore, max 64 chars)
  ValidWorkspaceName = fun name =>
    if name == "" then
      std.contract.blame_with_message "Workspace name cannot be empty" name
    else if std.string.length name > 64 then
      std.contract.blame_with_message "Workspace name must be <= 64 characters" name
    else if !std.string.matches "^[a-z0-9_-]+$" name then
      std.contract.blame_with_message
        "Workspace name must contain only lowercase alphanumeric, hyphen, or underscore"
        name
    else
      name,

  # Validate service name
  ValidServiceName = fun name =>
    if name == "" then
      std.contract.blame_with_message "Service name cannot be empty" name
    else if std.string.length name > 64 then
      std.contract.blame_with_message "Service name must be <= 64 characters" name
    else if !std.string.matches "^[a-z0-9_-]+$" name then
      std.contract.blame_with_message
        "Service name must contain only lowercase alphanumeric, hyphen, or underscore"
        name
    else
      name,

  # Validate filesystem path
  ValidFilesystemPath = fun path =>
    if path == "" then
      std.contract.blame_with_message "Path cannot be empty" path
    else if std.string.length path > 255 then
      std.contract.blame_with_message "Path must be <= 255 characters" path
    else if std.string.starts_with path "/" then
      path
    else
      std.contract.blame_with_message "Path must be absolute (start with /)" path,

  # Validate relative path
  ValidRelativePath = fun path =>
    if path == "" then
      std.contract.blame_with_message "Path cannot be empty" path
    else if std.string.length path > 255 then
      std.contract.blame_with_message "Path must be <= 255 characters" path
    else
      path,

  # Validate hostname/domain
  ValidHostname = fun hostname =>
    if hostname == "" then
      std.contract.blame_with_message "Hostname cannot be empty" hostname
    else if std.string.length hostname > 253 then
      std.contract.blame_with_message "Hostname must be <= 253 characters" hostname
    else if !std.string.matches "^[a-zA-Z0-9.-]+$" hostname then
      std.contract.blame_with_message
        "Hostname must contain only alphanumeric, dot, or hyphen"
        hostname
    else
      hostname,

  # Validate IP address (basic check)
  ValidIpAddress = fun ip =>
    if ip == "" then
      std.contract.blame_with_message "IP address cannot be empty" ip
    else if !std.string.matches "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$|^[0-9a-fA-F:]+$" ip then
      std.contract.blame_with_message
        "IP address format invalid (IPv4 or IPv6)"
        ip
    else
      ip,

  # Validate URL
  ValidUrl = fun url =>
    if url == "" then
      std.contract.blame_with_message "URL cannot be empty" url
    else if !std.string.matches "^https?://" url then
      std.contract.blame_with_message
        "URL must start with http:// or https://"
        url
    else
      url,

  # Validate password minimum length
  ValidPassword = fun password =>
    if std.string.length password < 8 then
      std.contract.blame_with_message
        "Password must be >= 8 characters"
        password
    else if std.string.length password > 128 then
      std.contract.blame_with_message
        "Password must be <= 128 characters"
        password
    else
      password,

  # Validate JWT token format
  ValidJwtToken = fun token =>
    if token == "" then
      std.contract.blame_with_message "JWT token cannot be empty" token
    else if !std.string.matches "^[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+$" token then
      std.contract.blame_with_message
        "JWT token format invalid (must be three base64url parts separated by dots)"
        token
    else
      token,

  # Validate identifier (alphanumeric, underscore, hyphen)
  ValidIdentifier = fun identifier =>
    if identifier == "" then
      std.contract.blame_with_message "Identifier cannot be empty" identifier
    else if !std.string.matches "^[a-z0-9_-]+$" identifier then
      std.contract.blame_with_message
        "Identifier must contain only lowercase alphanumeric, underscore, or hyphen"
        identifier
    else
      identifier,

  # Validate category/tag name
  ValidCategoryName = fun category =>
    if category == "" then
      std.contract.blame_with_message "Category cannot be empty" category
    else if !std.string.matches "^[a-z0-9_]+$" category then
      std.contract.blame_with_message
        "Category must contain only lowercase alphanumeric or underscore"
        category
    else
      category,
}
