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

TARGET_ROOT="${1:-.}"
BLACKSHIELD_API_URL="${BLACKSHIELD_API_URL:-https://api.blackshield.chaplau.com}"
BLACKSHIELD_VMS_IMAGE="${BLACKSHIELD_VMS_IMAGE:-public.ecr.aws/blackshield-security/vms-scanner:1.0.6}"

mkdir -p "$TARGET_ROOT/deploy/gcp-vm-scanner"

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

provider "google" {
  project = var.project_id
  region  = var.region
}

resource "google_project_service" "apis" {
  for_each = toset([
    "run.googleapis.com",
    "secretmanager.googleapis.com",
    "storage.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   = "blackshield-vm-scanner"
  display_name = "BlackShield VM Scanner"
  description  = "Cloud Run runtime for object-storage-backed VM alert ingestion"
}

resource "google_storage_bucket" "alerts" {
  project                     = var.project_id
  name                        = var.alerts_bucket_name != "" ? var.alerts_bucket_name : "${var.project_id}-blackshield-vm-alerts"
  location                    = var.bucket_location
  uniform_bucket_level_access = true
  public_access_prevention    = "enforced"

  versioning {
    enabled = true
  }

  depends_on = [google_project_service.apis]
}

resource "google_storage_bucket_iam_member" "scanner_read" {
  bucket = google_storage_bucket.alerts.name
  role   = "roles/storage.objectViewer"
  member = "serviceAccount:${google_service_account.scanner.email}"
}

resource "google_secret_manager_secret" "api_key" {
  project   = var.project_id
  secret_id = "blackshield-vm-scanner-api-key"

  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_secret_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_service" "scanner" {
  project  = var.project_id
  name     = "blackshield-vm-scanner"
  location = var.region
  ingress  = "INGRESS_TRAFFIC_ALL"

  template {
    service_account = google_service_account.scanner.email

    scaling {
      min_instance_count = 1
      max_instance_count = 1
    }

    containers {
      image = var.scanner_image

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

      env {
        name  = "VMS_COLLECTOR_MODE"
        value = "gcs"
      }

      env {
        name  = "VMS_SOURCE_URI"
        value = "gs://${google_storage_bucket.alerts.name}/${var.alerts_object_key}"
      }

      env {
        name  = "OSSEC_STATE_FILE"
        value = "/tmp/vms-state/ossec-state.json"
      }

      env {
        name  = "SCAN_INTERVAL_SECONDS"
        value = tostring(var.scan_interval_seconds)
      }

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

      env {
        name  = "MIN_SEVERITY"
        value = "high"
      }

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

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

      resources {
        limits = {
          cpu    = "1"
          memory = "512Mi"
        }
      }
    }
  }

  traffic {
    percent = 100
    type    = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
  }

  depends_on = [
    google_secret_manager_secret_iam_member.scanner_secret_read,
    google_storage_bucket_iam_member.scanner_read,
  ]
}
EOF

cat > "$TARGET_ROOT/deploy/gcp-vm-scanner/variables.tf" <<EOF
variable "project_id" {
  description = "Target GCP project ID."
  type        = string
}

variable "region" {
  description = "Region for the Cloud Run service."
  type        = string
  default     = "us-central1"
}

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

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

variable "scanner_image" {
  description = "Fully-qualified vms-scanner image URI."
  type        = string
  default     = "${BLACKSHIELD_VMS_IMAGE}"
}

variable "alerts_bucket_name" {
  description = "Optional existing bucket name override."
  type        = string
  default     = ""
}

variable "bucket_location" {
  description = "Bucket location."
  type        = string
  default     = "US"
}

variable "alerts_object_key" {
  description = "Object key that the Cloud Run service tails."
  type        = string
  default     = "prod/default/alerts.json"
}

variable "scan_interval_seconds" {
  description = "Polling interval in seconds for the GCS collector."
  type        = number
  default     = 60
}
EOF

cat > "$TARGET_ROOT/deploy/gcp-vm-scanner/outputs.tf" <<'EOF'
output "alerts_bucket_name" {
  description = "Bucket that stores uploaded VM alert objects."
  value       = google_storage_bucket.alerts.name
}

output "alerts_object_uri" {
  description = "Object URI that the VM scanner tails."
  value       = "gs://${google_storage_bucket.alerts.name}/${var.alerts_object_key}"
}

output "service_url" {
  description = "Cloud Run service URL."
  value       = google_cloud_run_v2_service.scanner.uri
}

output "service_account" {
  description = "Cloud Run service account email."
  value       = google_service_account.scanner.email
}
EOF

cat > "$TARGET_ROOT/deploy/gcp-vm-scanner/terraform.tfvars.example" <<'EOF'
project_id           = "my-prod-project"
region               = "us-central1"
blackshield_api_key  = "sp_xxxx"
alerts_object_key    = "prod/default/alerts.json"
scan_interval_seconds = 60
EOF

cat > "$TARGET_ROOT/deploy/gcp-vm-scanner/host-sync-to-gcs.sh" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

SOURCE_FILE="${1:-/var/ossec/logs/alerts/alerts.json}"
GCS_URI="${2:-gs://replace-me/prod/default/alerts.json}"
SYNC_INTERVAL_SECONDS="${SYNC_INTERVAL_SECONDS:-30}"

copy_command() {
  if command -v gcloud >/dev/null 2>&1; then
    gcloud storage cp "$SOURCE_FILE" "$GCS_URI"
    return
  fi
  if command -v gsutil >/dev/null 2>&1; then
    gsutil cp "$SOURCE_FILE" "$GCS_URI"
    return
  fi
  echo "gcloud or gsutil is required for host-sync-to-gcs.sh" >&2
  exit 1
}

while true; do
  if [ -f "$SOURCE_FILE" ]; then
    copy_command
  else
    echo "alerts file not found yet: $SOURCE_FILE" >&2
  fi
  sleep "$SYNC_INTERVAL_SECONDS"
done
EOF
chmod +x "$TARGET_ROOT/deploy/gcp-vm-scanner/host-sync-to-gcs.sh"

cat > "$TARGET_ROOT/deploy/gcp-vm-scanner/README.md" <<EOF
# GCP VM Scanner Bundle

1. Copy \`terraform.tfvars.example\` to \`terraform.tfvars\` and set
\`project_id\` and \`blackshield_api_key\`.
2. Deploy the Cloud Run service and versioned GCS bucket:

\`\`\`bash
terraform init
terraform apply -auto-approve
\`\`\`

3. Start the host-side upload helper from the OSSEC or Wazuh host once
\`terraform output alerts_object_uri\` is available:

\`\`\`bash
./host-sync-to-gcs.sh /var/ossec/logs/alerts/alerts.json gs://<bucket>/<object-key>
\`\`\`

The Cloud Run service runs continuously with \`VMS_COLLECTOR_MODE=gcs\` and
tails the uploaded object incrementally using object version plus byte-offset
state.
EOF

printf 'Wrote deploy/gcp-vm-scanner/main.tf\n'
printf 'Wrote deploy/gcp-vm-scanner/variables.tf\n'
printf 'Wrote deploy/gcp-vm-scanner/outputs.tf\n'
printf 'Wrote deploy/gcp-vm-scanner/terraform.tfvars.example\n'
printf 'Wrote deploy/gcp-vm-scanner/host-sync-to-gcs.sh\n'
printf 'Wrote deploy/gcp-vm-scanner/README.md\n'
