#!/usr/bin/env bash
set -euo pipefail

TARGET_ROOT="${1:-.}"
BLACKSHIELD_API_URL="${BLACKSHIELD_API_URL:-https://api.blackshield.chaplau.com}"
BLACKSHIELD_CLOUD_IMAGE="${BLACKSHIELD_CLOUD_IMAGE:-public.ecr.aws/blackshield-security/cloud-scanner:1.0.0}"

mkdir -p "$TARGET_ROOT/deploy/gcp-cloud-scanner"
cat > "$TARGET_ROOT/deploy/gcp-cloud-scanner/main.tf" <<'EOF'
terraform {
  required_version = ">= 1.7"
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {}

locals {
  targets = {
    "prod-us" = { project = "my-prod-project", region = "us-central1" }
    # "prod-eu" = { project = "my-prod-project", region = "europe-west1" }
  }
}

module "cloud_scanner" {
  for_each = local.targets
  source   = "./modules/cloud-scanner"

  project_id          = each.value.project
  region              = each.value.region
  scanner_image       = var.scanner_image
  blackshield_api_url = var.blackshield_api_url
  blackshield_api_key = var.blackshield_api_key
  schedule_cron       = var.schedule_cron
}
EOF

mkdir -p "$TARGET_ROOT/deploy/gcp-cloud-scanner/modules/cloud-scanner"
cat > "$TARGET_ROOT/deploy/gcp-cloud-scanner/modules/cloud-scanner/main.tf" <<'EOF'
locals {
  sa_name    = "blackshield-cloud-scanner"
  secret_id  = "blackshield-api-key"
  job_name   = "blackshield-cloud-scanner"
  sched_name = "blackshield-cloud-scanner-trigger"
}

resource "google_project_service" "apis" {
  for_each = toset([
    "run.googleapis.com",
    "cloudscheduler.googleapis.com",
    "secretmanager.googleapis.com",
    "iam.googleapis.com",
  ])
  project            = var.project_id
  service            = each.value
  disable_on_destroy = false
}

resource "google_service_account" "scanner" {
  project      = var.project_id
  account_id   = local.sa_name
  display_name = "BlackShield Cloud Scanner"
  description  = "Least-privilege service account for BlackShield Prowler scanner"
}

resource "google_project_iam_member" "scanner_roles" {
  for_each = toset([
    "roles/viewer",
    "roles/iam.securityReviewer",
    "roles/cloudasset.viewer",
    "roles/cloudkms.cryptoKeyEncrypterDecrypterViewer",
    "roles/logging.viewer",
    "roles/monitoring.viewer",
  ])
  project = var.project_id
  role    = each.value
  member  = "serviceAccount:${google_service_account.scanner.email}"
}

resource "google_secret_manager_secret" "api_key" {
  project   = var.project_id
  secret_id = local.secret_id

  replication {
    auto {}
  }

  depends_on = [google_project_service.apis]
}

resource "google_secret_manager_secret_version" "api_key" {
  secret      = google_secret_manager_secret.api_key.id
  secret_data = var.blackshield_api_key
}

resource "google_secret_manager_secret_iam_member" "scanner_read" {
  project   = var.project_id
  secret_id = google_secret_manager_secret.api_key.secret_id
  role      = "roles/secretmanager.secretAccessor"
  member    = "serviceAccount:${google_service_account.scanner.email}"
}

resource "google_cloud_run_v2_job" "scanner" {
  project  = var.project_id
  name     = local.job_name
  location = var.region
  labels = {
    "managed-by" = "terraform"
    component    = "cloud-scanner"
  }

  template {
    task_count  = 1
    parallelism = 1

    template {
      service_account = google_service_account.scanner.email
      max_retries     = 1
      timeout         = "${var.job_timeout_seconds}s"

      containers {
        image = var.scanner_image

        env {
          name  = "BLACKSHIELD_API_URL"
          value = var.blackshield_api_url
        }

        env {
          name  = "CLOUD_PROVIDER"
          value = "gcp"
        }

        env {
          name  = "SCAN_INTERVAL_SECONDS"
          value = "0"
        }

        env {
          name  = "SCAN_ON_STARTUP"
          value = "true"
        }

        env {
          name  = "LOG_LEVEL"
          value = "INFO"
        }

        env {
          name  = "BATCH_SIZE"
          value = "500"
        }

        env {
          name = "BLACKSHIELD_API_KEY"
          value_source {
            secret_key_ref {
              secret  = google_secret_manager_secret.api_key.secret_id
              version = "latest"
            }
          }
        }

        resources {
          limits = {
            cpu    = var.cpu
            memory = var.memory
          }
        }
      }
    }
  }

  depends_on = [
    google_secret_manager_secret_iam_member.scanner_read,
    google_project_service.apis,
  ]
}

resource "google_service_account" "scheduler" {
  project      = var.project_id
  account_id   = "blackshield-scheduler"
  display_name = "BlackShield Cloud Scheduler invoker"
}

resource "google_cloud_run_v2_job_iam_member" "scheduler_invoke" {
  project  = var.project_id
  location = var.region
  name     = google_cloud_run_v2_job.scanner.name
  role     = "roles/run.invoker"
  member   = "serviceAccount:${google_service_account.scheduler.email}"
}

resource "google_cloud_scheduler_job" "trigger" {
  project          = var.project_id
  region           = var.region
  name             = local.sched_name
  description      = "Trigger BlackShield cloud scanner"
  schedule         = var.schedule_cron
  time_zone        = "UTC"
  attempt_deadline = "${var.job_timeout_seconds}s"

  http_target {
    uri         = "https://${var.region}-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/${var.project_id}/jobs/${local.job_name}:run"
    http_method = "POST"

    oauth_token {
      service_account_email = google_service_account.scheduler.email
    }
  }

  depends_on = [google_project_service.apis]
}
EOF

mkdir -p "$TARGET_ROOT/deploy/gcp-cloud-scanner/modules/cloud-scanner"
cat > "$TARGET_ROOT/deploy/gcp-cloud-scanner/modules/cloud-scanner/outputs.tf" <<'EOF'
output "job_name" {
  description = "Cloud Run Job name."
  value       = google_cloud_run_v2_job.scanner.name
}

output "scheduler_name" {
  description = "Cloud Scheduler job name."
  value       = google_cloud_scheduler_job.trigger.name
}

output "scanner_service_account" {
  description = "Scanner service account email."
  value       = google_service_account.scanner.email
}
EOF

mkdir -p "$TARGET_ROOT/deploy/gcp-cloud-scanner/modules/cloud-scanner"
cat > "$TARGET_ROOT/deploy/gcp-cloud-scanner/modules/cloud-scanner/variables.tf" <<'EOF'
variable "project_id" {
  description = "GCP project ID."
  type        = string
}

variable "region" {
  description = "GCP region for Cloud Run and Scheduler."
  type        = string
}

variable "scanner_image" {
  description = "Fully-qualified container image URI."
  type        = string
}

variable "blackshield_api_url" {
  description = "BlackShield API base URL."
  type        = string
}

variable "blackshield_api_key" {
  description = "BlackShield ingestion API key."
  type        = string
  sensitive   = true
}

variable "schedule_cron" {
  description = "Cloud Scheduler cron expression (UTC)."
  type        = string
  default     = "0 */6 * * *"
}

variable "job_timeout_seconds" {
  description = "Maximum Cloud Run Job execution time in seconds."
  type        = number
  default     = 1800
}

variable "cpu" {
  description = "CPU allocation for the Cloud Run Job task."
  type        = string
  default     = "2"
}

variable "memory" {
  description = "Memory allocation for the Cloud Run Job task."
  type        = string
  default     = "4Gi"
}
EOF

mkdir -p "$TARGET_ROOT/deploy/gcp-cloud-scanner"
cat > "$TARGET_ROOT/deploy/gcp-cloud-scanner/outputs.tf" <<'EOF'
output "cloud_run_job_names" {
  description = "Cloud Run Job names by target."
  value = {
    for key, module_instance in module.cloud_scanner :
    key => module_instance.job_name
  }
}

output "scheduler_job_names" {
  description = "Cloud Scheduler job names by target."
  value = {
    for key, module_instance in module.cloud_scanner :
    key => module_instance.scheduler_name
  }
}
EOF

mkdir -p "$TARGET_ROOT/deploy/gcp-cloud-scanner"
cat > "$TARGET_ROOT/deploy/gcp-cloud-scanner/variables.tf" <<EOF
variable "blackshield_api_key" {
  description = "BlackShield ingestion API key."
  type        = string
  sensitive   = true
}

variable "blackshield_api_url" {
  description = "BlackShield API base URL."
  type        = string
  default     = "$BLACKSHIELD_API_URL"
}

variable "scanner_image" {
  description = "Fully-qualified container image URI."
  type        = string
  default     = "$BLACKSHIELD_CLOUD_IMAGE"
}

variable "schedule_cron" {
  description = "Cloud Scheduler cron expression (UTC)."
  type        = string
  default     = "0 */6 * * *"
}
EOF

printf "Wrote source bundle files:
"
printf "  - %s\n" "$TARGET_ROOT/deploy/gcp-cloud-scanner/main.tf"
printf "  - %s\n" "$TARGET_ROOT/deploy/gcp-cloud-scanner/modules/cloud-scanner/main.tf"
printf "  - %s\n" "$TARGET_ROOT/deploy/gcp-cloud-scanner/modules/cloud-scanner/outputs.tf"
printf "  - %s\n" "$TARGET_ROOT/deploy/gcp-cloud-scanner/modules/cloud-scanner/variables.tf"
printf "  - %s\n" "$TARGET_ROOT/deploy/gcp-cloud-scanner/outputs.tf"
printf "  - %s\n" "$TARGET_ROOT/deploy/gcp-cloud-scanner/variables.tf"
