variable "target_account_id" {
  description = "AWS account in which the environment is allowed to run."
  type        = string
  default     = "118688039167"

  validation {
    condition     = can(regex("^[0-9]{12}$", var.target_account_id))
    error_message = "target_account_id must be a 12-digit AWS account ID."
  }
}

variable "aws_profile" {
  description = "Local AWS CLI/SDK profile used by Terraform and helper scripts."
  type        = string
  default     = "118688039167-cp9"

  validation {
    condition     = can(regex("^[A-Za-z0-9._-]+$", var.aws_profile))
    error_message = "aws_profile contains unsupported characters."
  }
}

variable "aws_region" {
  description = "AWS region for the environment."
  type        = string
  default     = "us-west-2"

  validation {
    condition     = can(regex("^[a-z]{2}(-[a-z]+)+-[0-9]+$", var.aws_region))
    error_message = "aws_region must be a valid AWS region name."
  }
}

variable "name_prefix" {
  description = "Prefix applied to AWS resource names and tags."
  type        = string
  default     = "date-integration-test"

  validation {
    condition     = can(regex("^[a-z0-9-]{3,24}$", var.name_prefix))
    error_message = "name_prefix must contain 3-24 lowercase letters, digits, or hyphens."
  }
}

variable "s3_bucket_name" {
  description = "Optional globally unique S3 bucket name. A deployment-specific name is generated when omitted."
  type        = string
  default     = null
  nullable    = true

  validation {
    condition     = var.s3_bucket_name == null ? true : can(regex("^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$", var.s3_bucket_name))
    error_message = "s3_bucket_name must be null or a valid 3-63 character S3 bucket name."
  }
}

variable "s3_force_destroy" {
  description = "Delete disposable CDC, backup-export, and cluster-export objects when destroying the test bucket."
  type        = bool
  default     = true
}

variable "s3_role_trusted_principal_arns" {
  description = "AWS principals allowed to assume the generated S3 access role. Defaults to the target account root."
  type        = set(string)
  default     = null
  nullable    = true

  validation {
    condition = var.s3_role_trusted_principal_arns == null ? true : length(var.s3_role_trusted_principal_arns) > 0 && alltrue([
      for arn in var.s3_role_trusted_principal_arns : can(regex("^arn:aws:iam::[0-9]{12}:(root|role/.+|user/.+)$", arn))
    ])
    error_message = "s3_role_trusted_principal_arns must contain at least one IAM root, role, or user ARN."
  }
}

variable "s3_role_external_id" {
  description = "Optional ExternalId required when assuming the generated S3 access role."
  type        = string
  default     = null
  nullable    = true
  sensitive   = true

  validation {
    condition     = var.s3_role_external_id == null ? true : can(regex("^[A-Za-z0-9+=,.@:/_-]{2,1224}$", var.s3_role_external_id))
    error_message = "s3_role_external_id must be 2-1224 AWS STS-safe characters when set."
  }
}

variable "s3_backup_export_access_grants" {
  description = "Cross-account role patterns allowed to write backup exports. Add stable map entries for additional consumers."
  type = map(object({
    account_id       = string
    role_arn_pattern = string
  }))
  default = {}

  validation {
    condition = alltrue([
      for name in keys(var.s3_backup_export_access_grants) : can(regex("^[a-z][a-z0-9-]{0,19}$", name))
    ])
    error_message = "s3_backup_export_access_grants keys must be 1-20 lowercase alphanumeric or hyphen characters and start with a letter."
  }

  validation {
    condition = alltrue([
      for grant in values(var.s3_backup_export_access_grants) :
      can(regex("^[0-9]{12}$", grant.account_id)) &&
      can(regex("^arn:aws:iam::${grant.account_id}:role/[A-Za-z0-9+=,.@_*/?-]+$", grant.role_arn_pattern))
    ])
    error_message = "Each S3 backup-export grant must contain a 12-digit account ID and a matching IAM role ARN pattern."
  }
}

variable "s3_assume_role_grants" {
  description = "Account and external-ID pairs permitted to assume the fixture bucket's pre-provisioned S3 access role. The role is limited to bucket metadata and multipart object operations, including ACLs and tags, under cdc/, backup-export/, and cluster-export/, plus read-only object access under import/."
  type = map(object({
    account_id  = string
    external_id = string
  }))
  default = {}

  validation {
    condition = alltrue([
      for name in keys(var.s3_assume_role_grants) : can(regex("^[a-z][a-z0-9-]{0,19}$", name))
    ])
    error_message = "s3_assume_role_grants keys must be 1-20 lowercase alphanumeric or hyphen characters and start with a letter."
  }

  validation {
    condition = alltrue([
      for grant in values(var.s3_assume_role_grants) :
      can(regex("^[0-9]{12}$", grant.account_id)) &&
      length(grant.external_id) >= 2 && length(grant.external_id) <= 1224 &&
      can(regex("^[A-Za-z0-9+=,.@:/_-]+$", grant.external_id))
    ])
    error_message = "Each S3 assume-role grant must contain a 12-digit account ID and a 2-1224 character STS-safe external ID."
  }
}

variable "vpc_cidr" {
  description = "CIDR for the dedicated VPC. A /20 is recommended."
  type        = string
  default     = "10.88.0.0/20"

  validation {
    condition     = can(cidrsubnet(var.vpc_cidr, 4, 15))
    error_message = "vpc_cidr must be a valid CIDR with room for one child subnet per available AZ."
  }
}

variable "instance_type" {
  description = "ARM64 EC2 instance type. c8g.large (2 vCPU, 4 GiB) is the default."
  type        = string
  default     = "c8g.large"

  validation {
    condition     = can(regex("^[a-z0-9]+[a-z0-9.-]*$", var.instance_type))
    error_message = "instance_type is not a valid EC2 instance type string."
  }
}

variable "ami_id" {
  description = "Optional ARM64 AL2023-compatible AMI override. The latest official ARM64 AL2023 AMI is used by default."
  type        = string
  default     = null
  nullable    = true

  validation {
    condition     = var.ami_id == null ? true : can(regex("^ami-[0-9a-f]+$", var.ami_id))
    error_message = "ami_id must be null or a valid AMI ID."
  }
}

variable "root_volume_size_gib" {
  description = "Encrypted gp3 root volume size."
  type        = number
  default     = 30

  validation {
    condition     = var.root_volume_size_gib >= 20 && var.root_volume_size_gib <= 200
    error_message = "root_volume_size_gib must be between 20 and 200."
  }
}

variable "data_volume_size_gib" {
  description = "Encrypted gp3 data volume size."
  type        = number
  default     = 50

  validation {
    condition     = var.data_volume_size_gib >= 20 && var.data_volume_size_gib <= 1000
    error_message = "data_volume_size_gib must be between 20 and 1000."
  }
}

variable "desired_state" {
  description = "Requested EC2 state. Bootstrap always completes before an initial stop."
  type        = string
  default     = "running"

  validation {
    condition     = contains(["running", "stopped"], var.desired_state)
    error_message = "desired_state must be running or stopped."
  }
}

variable "remove_privatelink_when_stopped" {
  description = "Delete the shared NLB and endpoint service while desired_state is stopped. A new service name is created on wake."
  type        = bool
  default     = false
}

variable "port_base" {
  description = "Optional stable base for all high external ports. A random value is generated when omitted."
  type        = number
  default     = null
  nullable    = true

  validation {
    condition     = var.port_base == null ? true : var.port_base >= 20000 && var.port_base <= 60000 && floor(var.port_base) == var.port_base
    error_message = "port_base must be a whole number between 20000 and 60000."
  }
}

variable "allowed_principal_arns" {
  description = "AWS principals allowed to discover the endpoint service and create interface endpoints. Defaults to the approved Date Integration consumer accounts plus the producer account."
  type        = set(string)
  default     = null
  nullable    = true

  validation {
    condition = var.allowed_principal_arns == null ? true : alltrue([
      for arn in var.allowed_principal_arns : can(regex("^arn:aws:iam::[0-9]{12}:(root|role/.+|user/.+)$", arn))
    ])
    error_message = "allowed_principal_arns must contain IAM root, role, or user ARNs."
  }
}

variable "e2e_project_ids" {
  description = "Comma-separated TiDB Cloud project IDs associated with generated Kafka PrivateLink E2E dependencies."
  type        = string
  default     = "1369847559694040763,1369847559694040575"

  validation {
    condition     = can(regex("^[0-9]+(,[0-9]+)*$", var.e2e_project_ids))
    error_message = "e2e_project_ids must be one or more numeric project IDs separated by commas."
  }
}

variable "kafka_privatelink_root_domain_name" {
  description = "Consumer-side private DNS root used by Kafka Proxy advertised metadata."
  type        = string
  default     = "date-integration.kafka.test"

  validation {
    condition     = can(regex("^[a-z0-9][a-z0-9.-]*[a-z0-9]$", var.kafka_privatelink_root_domain_name))
    error_message = "kafka_privatelink_root_domain_name must be a lowercase DNS name."
  }
}

variable "kafka_privatelink_advertised_host" {
  description = "Optional exact advertised broker hostname. Defaults to b1.<primary-az-id>.<root-domain>."
  type        = string
  default     = null
  nullable    = true

  validation {
    condition     = var.kafka_privatelink_advertised_host == null ? true : can(regex("^[a-z0-9][a-z0-9.-]*[a-z0-9]$", var.kafka_privatelink_advertised_host))
    error_message = "kafka_privatelink_advertised_host must be null or a lowercase DNS name."
  }
}

variable "mysql_user" {
  description = "MySQL application/E2E administrator user."
  type        = string
  default     = "e2e_admin"

  validation {
    condition     = can(regex("^[A-Za-z][A-Za-z0-9_]{2,31}$", var.mysql_user))
    error_message = "mysql_user must be 3-32 alphanumeric/underscore characters and start with a letter."
  }
}

variable "mysql_root_password" {
  description = "Optional MySQL root password. Randomly generated when omitted."
  type        = string
  default     = null
  nullable    = true
  sensitive   = true

  validation {
    condition     = var.mysql_root_password == null ? true : can(regex("^[A-Za-z0-9!@%^*_.+=~-]{16,128}$", var.mysql_root_password))
    error_message = "mysql_root_password must be 16-128 shell/env-safe characters."
  }
}

variable "mysql_password" {
  description = "Optional MySQL E2E user password. Randomly generated when omitted."
  type        = string
  default     = null
  nullable    = true
  sensitive   = true

  validation {
    condition     = var.mysql_password == null ? true : can(regex("^[A-Za-z0-9!@%^*_.+=~-]{16,128}$", var.mysql_password))
    error_message = "mysql_password must be 16-128 shell/env-safe characters."
  }
}

variable "kafka_sasl_username" {
  description = "Optional Kafka SASL/PLAIN username. Randomly generated when omitted."
  type        = string
  default     = null
  nullable    = true
  sensitive   = true

  validation {
    condition     = var.kafka_sasl_username == null ? true : can(regex("^[A-Za-z][A-Za-z0-9_.-]{2,31}$", var.kafka_sasl_username))
    error_message = "kafka_sasl_username must be 3-32 safe characters and start with a letter."
  }
}

variable "kafka_sasl_password" {
  description = "Optional Kafka SASL/PLAIN password. Randomly generated when omitted."
  type        = string
  default     = null
  nullable    = true
  sensitive   = true

  validation {
    condition     = var.kafka_sasl_password == null ? true : can(regex("^[A-Za-z0-9!@%^*_.+=~-]{16,128}$", var.kafka_sasl_password))
    error_message = "kafka_sasl_password must be 16-128 shell/env-safe characters."
  }
}

variable "pulsar_token_secret" {
  description = "Optional base64-encoded 256-bit Pulsar JWT HMAC key. Randomly generated when omitted."
  type        = string
  default     = null
  nullable    = true
  sensitive   = true

  validation {
    condition     = var.pulsar_token_secret == null ? true : can(base64decode(var.pulsar_token_secret)) && length(base64decode(var.pulsar_token_secret)) >= 32
    error_message = "pulsar_token_secret must decode to at least 32 bytes."
  }
}

variable "enable_pulsar" {
  description = "Deploy Pulsar Standalone and Pulsar Proxy."
  type        = bool
  default     = true
}

variable "enable_schema_registry" {
  description = "Deploy a Confluent-compatible Schema Registry."
  type        = bool
  default     = true
}

variable "schema_registry_username" {
  type      = string
  default   = null
  nullable  = true
  sensitive = true
}

variable "schema_registry_password" {
  type      = string
  default   = null
  nullable  = true
  sensitive = true
}
