variable "env" {
  type = string
}

variable "deploy_type" {
  type = string
}

variable "service_plan" {
  type    = string
  default = ""
}

variable "cloud_provider" {
  type = string
}

variable "cloud_region" {
  type = string
}

variable "logical_region_name" {
  type = string
}

variable "service_address" {
  type = string
}

variable "dataplane_accounts" {
  type = list(string)
}

variable "audit_log_bucket" {
  type    = string
  default = ""
}

variable "audit_log_storage_account_name" {
  type    = string
  default = ""
}

variable "shared_bucket" {
  type    = string
  default = ""
}

variable "tenant_ids" {
  type        = list(string)
  default     = []
  description = "TiDB Cloud tenant (org) ids that should be whitelisted for this region. When non-empty, they are added to regionWhiteLists under the matching servicePlan entry; when empty, no whitelist entry is written."
}

locals {
  accounts_str = join(" ", var.dataplane_accounts)
}

data "external" "env_check" {
  program = ["bash", "-c", <<-EOT
        cat <<EOF
        {
            "auth_key": "$GLOBAL_AUTH_KEY",
            "public_key": "$DATA_SERVICE_PUBLIC_KEY",
            "private_key": "$DATA_SERVICE_PRIVATE_KEY"
        }
        EOF
    EOT
  ]

  lifecycle {
    postcondition {
      condition     = self.result.auth_key != ""
      error_message = "env GLOBAL_AUTH_KEY not set"
    }
    postcondition {
      condition     = self.result.public_key != ""
      error_message = "env DATA_SERVICE_PUBLIC_KEY not set"
    }
    postcondition {
      condition     = self.result.private_key != ""
      error_message = "env DATA_SERVICE_PRIVATE_KEY not set"
    }
  }
}


data "local_command" "provider_regions" {
  command = "bash"
  arguments = ["-c", <<-EOT
    curl -s --digest --user $DATA_SERVICE_PUBLIC_KEY:$DATA_SERVICE_PRIVATE_KEY \
      'https://us-west-2.data.tidbcloud.com/api/v1beta/app/dataapp-WObJIvhw/endpoint/provider_regions' \
      | jq '.data.rows' | base64
  EOT
  ]
  depends_on = [data.external.env_check]
}

locals {
  regions          = jsondecode(base64decode(data.local_command.provider_regions.stdout))
  provider_regions = [for r in local.regions : r if r.provider == var.cloud_provider && r.name == var.cloud_region]
}

data "local_command" "default_backup_time" {
  command   = "uv"
  arguments = ["run", "${path.module}/scripts/get_default_backup_time.py", local.provider_regions.0.timezone]

  lifecycle {
    precondition {
      condition     = length(local.provider_regions) == 1
      error_message = "region ${var.cloud_region} of provider ${var.cloud_provider} not found"
    }

    postcondition {
      condition     = try(regex("^\\d\\d:\\d\\d$", self.stdout), "") != ""
      error_message = "get default backup time for timezone ${local.provider_regions.0.timezone} failed"
    }
  }
}

resource "terraform_data" "default_backup_time" {
  # Prevent inconsistent backup times across the year in time zones with Daylight Saving Time (DST)
  input = data.local_command.default_backup_time.stdout

  lifecycle {
    ignore_changes = all
  }
}

resource "null_resource" "create_region" {
  lifecycle {
    ignore_changes = all
  }

  triggers = {
    env                            = var.env
    deploy_type                    = var.deploy_type
    service_plan                   = var.service_plan
    cloud_provider                 = var.cloud_provider
    cloud_region                   = var.cloud_region
    logical_region_name            = var.logical_region_name
    service_address                = var.service_address
    accounts_str                   = local.accounts_str
    display_name                   = local.provider_regions.0.display_name
    country                        = local.provider_regions.0.country
    area                           = local.provider_regions.0.area
    default_backup_time            = terraform_data.default_backup_time.output
    audit_log_bucket               = var.audit_log_bucket
    audit_log_storage_account_name = var.audit_log_storage_account_name
    shared_bucket                  = var.shared_bucket
    tenant_ids_str                 = join(",", var.tenant_ids)
  }

  provisioner "local-exec" {
    command = <<-EOT
        uv run ${path.module}/scripts/create_region_if_not_exist.py \
            --env ${self.triggers.env} \
            --deploy-type ${self.triggers.deploy_type} \
            --service-plan '${self.triggers.service_plan}' \
            --provider ${self.triggers.cloud_provider} \
            --region ${self.triggers.cloud_region} \
            --logical-region-name ${self.triggers.logical_region_name} \
            --service-address ${self.triggers.service_address} \
            --dataplane-accounts ${self.triggers.accounts_str} \
            --display-name "${self.triggers.display_name}" \
            --country-code ${self.triggers.country} \
            --area '${self.triggers.area}' \
            --default-backup-time ${self.triggers.default_backup_time} \
            ${self.triggers.audit_log_bucket != "" ? "--audit-log-bucket ${self.triggers.audit_log_bucket}" : ""} \
            ${self.triggers.audit_log_storage_account_name != "" ? "--audit-log-storage-account-name ${self.triggers.audit_log_storage_account_name}" : ""} \
            ${self.triggers.shared_bucket != "" ? "--shared-bucket ${self.triggers.shared_bucket}" : ""} \
            ${self.triggers.tenant_ids_str != "" ? "--tenant-ids ${self.triggers.tenant_ids_str}" : ""} \
            --state ACTIVE
    EOT
    when    = create
  }

  provisioner "local-exec" {
    command = <<-EOT
        uv run ${path.module}/scripts/delete_region.py \
            --env ${self.triggers.env} \
            --logical-region-name ${self.triggers.logical_region_name} \
            --deploy-type ${self.triggers.deploy_type} \
            --service-plan '${self.triggers.service_plan}' \
            --provider ${self.triggers.cloud_provider}
    EOT
    when    = destroy
  }
}

resource "null_resource" "update_region" {
  depends_on = [null_resource.create_region]

  triggers = {
    env                            = var.env
    deploy_type                    = var.deploy_type
    service_plan                   = var.service_plan
    cloud_provider                 = var.cloud_provider
    cloud_region                   = var.cloud_region
    logical_region_name            = var.logical_region_name
    service_address                = var.service_address
    accounts_str                   = local.accounts_str
    display_name                   = local.provider_regions.0.display_name
    country                        = local.provider_regions.0.country
    area                           = local.provider_regions.0.area
    default_backup_time            = terraform_data.default_backup_time.output
    audit_log_bucket               = var.audit_log_bucket
    audit_log_storage_account_name = var.audit_log_storage_account_name
    shared_bucket                  = var.shared_bucket
    tenant_ids_str                 = join(",", var.tenant_ids)
  }

  provisioner "local-exec" {
    command = <<-EOT
        uv run ${path.module}/scripts/update_region.py \
            --env ${self.triggers.env} \
            --deploy-type ${self.triggers.deploy_type} \
            --service-plan '${self.triggers.service_plan}' \
            --provider ${self.triggers.cloud_provider} \
            --region ${self.triggers.cloud_region} \
            --logical-region-name ${self.triggers.logical_region_name} \
            --service-address ${self.triggers.service_address} \
            --dataplane-accounts ${self.triggers.accounts_str} \
            --display-name "${self.triggers.display_name}" \
            --country-code ${self.triggers.country} \
            --area '${self.triggers.area}' \
            --default-backup-time ${self.triggers.default_backup_time} \
            ${self.triggers.audit_log_bucket != "" ? "--audit-log-bucket ${self.triggers.audit_log_bucket}" : ""} \
            ${self.triggers.audit_log_storage_account_name != "" ? "--audit-log-storage-account-name ${self.triggers.audit_log_storage_account_name}" : ""} \
            ${self.triggers.shared_bucket != "" ? "--shared-bucket ${self.triggers.shared_bucket}" : ""} \
            ${self.triggers.tenant_ids_str != "" ? "--tenant-ids ${self.triggers.tenant_ids_str}" : ""} \
            --state ACTIVE
    EOT
  }
}
