# ============================================================
# OmniCommerce Cloud — Terraform GCP Infrastructure
# GKE, Cloud SQL, Memorystore, Elasticsearch, Pub/Sub, Cloud Storage
# ============================================================

terraform {
  required_version = ">= 1.7.0"

  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.30"
    }
    google-beta = {
      source  = "hashicorp/google-beta"
      version = "~> 5.30"
    }
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 2.30"
    }
    helm = {
      source  = "hashicorp/helm"
      version = "~> 2.13"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.6"
    }
  }

  backend "gcs" {
    bucket = "omnicommerce-terraform-state"
    prefix = "gcp/production"
  }
}

provider "google" {
  project = var.gcp_project_id
  region  = var.gcp_region
}

provider "google-beta" {
  project = var.gcp_project_id
  region  = var.gcp_region
}

# ============================================================
# VARIABLES
# ============================================================

variable "gcp_project_id" {
  description = "GCP Project ID"
}

variable "gcp_region" {
  default     = "us-central1"
  description = "GCP region"
}

variable "environment" {
  default     = "production"
  description = "Environment name"
}

variable "domain_name" {
  default = "omnicommerce.io"
}

variable "gke_cluster_version" {
  default = "1.29"
}

# ============================================================
# NETWORK
# ============================================================

resource "google_compute_network" "vpc" {
  name                    = "omnicommerce-${var.environment}"
  auto_create_subnetworks = false
  routing_mode            = "REGIONAL"
}

resource "google_compute_subnetwork" "subnet" {
  name          = "omnicommerce-${var.environment}-subnet"
  network       = google_compute_network.vpc.id
  region        = var.gcp_region
  ip_cidr_range = "10.0.0.0/18"

  private_ip_google_access = true

  secondary_ip_range {
    range_name    = "pods"
    ip_cidr_range = "10.1.0.0/16"
  }

  secondary_ip_range {
    range_name    = "services"
    ip_cidr_range = "10.2.0.0/20"
  }
}

resource "google_compute_global_address" "private_ip_psa" {
  name          = "omnicommerce-psa-${var.environment}"
  purpose       = "VPC_PEERING"
  address_type  = "INTERNAL"
  prefix_length = 16
  network       = google_compute_network.vpc.id
}

resource "google_service_networking_connection" "private_vpc" {
  network                 = google_compute_network.vpc.id
  service                 = "servicenetworking.googleapis.com"
  reserved_peering_ranges = [google_compute_global_address.private_ip_psa.name]
}

resource "google_compute_firewall" "allow_internal" {
  name    = "omnicommerce-allow-internal"
  network = google_compute_network.vpc.id

  allow {
    protocol = "tcp"
    ports    = ["0-65535"]
  }
  allow {
    protocol = "udp"
    ports    = ["0-65535"]
  }

  source_ranges = ["10.0.0.0/18", "10.1.0.0/16", "10.2.0.0/20"]
}

resource "google_compute_firewall" "allow_health_checks" {
  name    = "omnicommerce-allow-health-checks"
  network = google_compute_network.vpc.id

  allow {
    protocol = "tcp"
    ports    = ["80", "443", "8080", "3000"]
  }

  source_ranges = ["35.191.0.0/16", "130.211.0.0/22", "209.85.152.0/22", "209.85.204.0/22"]
}

# ============================================================
# GKE CLUSTER
# ============================================================

resource "google_container_cluster" "gke" {
  name     = "omnicommerce-${var.environment}"
  location = var.gcp_region

  remove_default_node_pool = true
  initial_node_count       = 1

  network    = google_compute_network.vpc.id
  subnetwork = google_compute_subnetwork.subnet.id

  ip_allocation_policy {
    cluster_secondary_range_name  = "pods"
    services_secondary_range_name = "services"
  }

  private_cluster_config {
    enable_private_nodes    = true
    enable_private_endpoint = false
    master_ipv4_cidr_block  = "172.16.0.0/28"
  }

  master_authorized_networks_config {
    cidr_blocks {
      cidr_block   = "10.0.0.0/18"
      display_name = "Internal"
    }
  }

  release_channel {
    channel = "REGULAR"
  }

  workload_identity_config {
    workload_pool = "${var.gcp_project_id}.svc.id.goog"
  }

  monitoring_config {
    enable_components = ["SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER", "SCHEDULER"]
  }

  logging_config {
    enable_components = ["SYSTEM_COMPONENTS", "WORKLOADS"]
  }

  deletion_protection = true
}

resource "google_container_node_pool" "system" {
  name     = "system-pool"
  cluster  = google_container_cluster.gke.name
  location = var.gcp_region

  node_count = 2

  node_config {
    machine_type = "e2-standard-2"
    disk_size_gb = 50
    disk_type    = "pd-ssd"
    preemptible  = false

    workload_metadata_config {
      mode = "GKE_METADATA"
    }

    labels = {
      nodegroup = "system"
    }

    taint {
      key    = "CriticalAddonsOnly"
      value  = "true"
      effect = "NO_SCHEDULE"
    }

    oauth_scopes = [
      "https://www.googleapis.com/auth/cloud-platform",
      "https://www.googleapis.com/auth/logging.write",
      "https://www.googleapis.com/auth/monitoring",
    ]
  }

  management {
    auto_repair  = true
    auto_upgrade = true
  }
}

resource "google_container_node_pool" "application" {
  name     = "application-pool"
  cluster  = google_container_cluster.gke.name
  location = var.gcp_region

  node_count = 3
  autoscaling {
    min_node_count = 3
    max_node_count = 25
  }

  node_config {
    machine_type = "c2d-standard-4"
    disk_size_gb = 100
    disk_type    = "pd-ssd"

    workload_metadata_config {
      mode = "GKE_METADATA"
    }

    labels = {
      nodegroup = "application"
    }

    oauth_scopes = [
      "https://www.googleapis.com/auth/cloud-platform",
    ]
  }

  management {
    auto_repair  = true
    auto_upgrade = true
  }
}

# ============================================================
# CLOUD SQL (PostgreSQL)
# ============================================================

resource "google_sql_database_instance" "postgres" {
  name             = "omnicommerce-${var.environment}"
  database_version = "POSTGRES_16"
  region           = var.gcp_region

  settings {
    tier              = "db-custom-4-16384"
    disk_type         = "PD_SSD"
    disk_size         = 500
    disk_autoresize   = true
    disk_autoresize_limit = 2000
    availability_type = var.environment == "production" ? "REGIONAL" : "ZONAL"

    ip_configuration {
      ipv4_enabled                                  = false
      private_network                               = google_compute_network.vpc.id
      enable_private_path_for_google_cloud_services = true
      require_ssl                                   = true
    }

    database_flags {
      name  = "max_connections"
      value = "500"
    }
    database_flags {
      name  = "shared_buffers"
      value = "4194304"
    }
    database_flags {
      name  = "work_mem"
      value = "26214"
    }

    backup_configuration {
      enabled                        = true
      start_time                     = "03:00"
      point_in_time_recovery_enabled = true
      transaction_log_retention_days = 7
      backup_retention_settings {
        retained_backups = 30
        retention_unit   = "COUNT"
      }
    }

    insights_config {
      query_insights_enabled  = true
      query_string_length     = 4096
      record_application_tags = true
      record_client_address   = true
    }

    maintenance_window {
      day  = 7
      hour = 4
    }
  }

  deletion_protection = true
}

resource "google_sql_database" "main" {
  name     = "omnicommerce"
  instance = google_sql_database_instance.postgres.name
}

resource "random_password" "db" {
  length  = 32
  special = false
}

resource "google_sql_user" "app" {
  name     = "omni_app"
  instance = google_sql_database_instance.postgres.name
  password = random_password.db.result
}

# ============================================================
# MEMORYSTORE (Redis)
# ============================================================

resource "google_redis_instance" "cache" {
  name               = "omnicommerce-${var.environment}"
  tier               = var.environment == "production" ? "STANDARD_HA" : "BASIC"
  memory_size_gb     = var.environment == "production" ? 10 : 4
  region             = var.gcp_region
  authorized_network = google_compute_network.vpc.id
  connect_mode       = "PRIVATE_SERVICE_ACCESS"
  redis_version      = "REDIS_7_2"
  display_name       = "OmniCommerce Cache"

  redis_configs = {
    maxmemory-policy = "allkeys-lru"
    timeout          = "300"
    tcp-keepalive    = "300"
    maxclients       = "65000"
  }

  maintenance_policy {
    weekly_maintenance_window {
      day = "SUNDAY"
      start_time {
        hours   = 5
        minutes = 0
      }
    }
  }
}

# ============================================================
# CLOUD STORAGE (S3-compatible)
# ============================================================

resource "google_storage_bucket" "media" {
  name          = "omnicommerce-media-${var.environment}"
  location      = var.gcp_region
  storage_class = "STANDARD"
  force_destroy = false

  versioning {
    enabled = true
  }

  lifecycle_rule {
    action {
      type          = "SetStorageClass"
      storage_class = "NEARLINE"
    }
    condition {
      age = 90
    }
  }

  cors {
    origin          = ["https://*.${var.domain_name}"]
    method          = ["GET", "PUT", "POST", "DELETE", "HEAD"]
    response_header = ["*"]
    max_age_seconds = 3600
  }

  uniform_bucket_level_access = true
}

resource "google_storage_bucket_iam_member" "media_public" {
  bucket = google_storage_bucket.media.name
  role   = "roles/storage.objectViewer"
  member = "allUsers"
}

# ============================================================
# CLOUD CDN + LOAD BALANCER
# ============================================================

resource "google_compute_global_address" "cdn" {
  name = "omnicommerce-cdn-ip"
}

resource "google_compute_backend_bucket" "cdn" {
  name        = "omnicommerce-cdn-${var.environment}"
  bucket_name = google_storage_bucket.media.name
  enable_cdn  = true

  cdn_policy {
    cache_mode                   = "CACHE_ALL_STATIC"
    default_ttl                  = 86400
    max_ttl                      = 31536000
    client_ttl                   = 86400
    negative_caching             = true
    negative_caching_policy {
      code = 404
      ttl  = 300
    }
  }
}

resource "google_compute_url_map" "cdn" {
  name            = "omnicommerce-cdn-${var.environment}"
  default_service = google_compute_backend_bucket.cdn.id
}

resource "google_compute_managed_ssl_certificate" "cdn" {
  name = "omnicommerce-cdn-cert"
  managed {
    domains = ["cdn.${var.domain_name}"]
  }
}

resource "google_compute_target_https_proxy" "cdn" {
  name             = "omnicommerce-cdn-proxy"
  url_map          = google_compute_url_map.cdn.id
  ssl_certificates = [google_compute_managed_ssl_certificate.cdn.id]
}

resource "google_compute_global_forwarding_rule" "cdn" {
  name       = "omnicommerce-cdn-forwarding"
  target     = google_compute_target_https_proxy.cdn.id
  port_range = "443"
  ip_address = google_compute_global_address.cdn.address
}

# ============================================================
# PUB/SUB (Kafka alternative)
# ============================================================

resource "google_pubsub_topic" "events" {
  name = "omnicommerce-events"

  message_retention_duration = "604800s" # 7 days
}

resource "google_pubsub_topic" "notifications" {
  name = "omnicommerce-notifications"
}

resource "google_pubsub_topic" "orders" {
  name = "omnicommerce-orders"
}

resource "google_pubsub_subscription" "order_processor" {
  name  = "omnicommerce-order-processor"
  topic = google_pubsub_topic.orders.name

  ack_deadline_seconds = 600

  retry_policy {
    minimum_backoff = "10s"
    maximum_backoff = "600s"
  }

  dead_letter_policy {
    dead_letter_topic     = google_pubsub_topic.orders_dlq.id
    max_delivery_attempts = 5
  }
}

resource "google_pubsub_topic" "orders_dlq" {
  name = "omnicommerce-orders-dlq"
}

# ============================================================
# ARTIFACT REGISTRY
# ============================================================

resource "google_artifact_registry_repository" "docker" {
  location      = var.gcp_region
  repository_id = "omnicommerce-docker"
  format        = "DOCKER"

  docker_config {
    immutable_tags = true
  }
}

# ============================================================
# SECRET MANAGER
# ============================================================

resource "google_secret_manager_secret" "db_url" {
  secret_id = "omnicommerce-db-url"

  replication {
    auto {}
  }
}

resource "google_secret_manager_secret_version" "db_url" {
  secret      = google_secret_manager_secret.db_url.id
  secret_data = "postgres://omni_app:${random_password.db.result}@${google_sql_database_instance.postgres.private_ip_address}:5432/omnicommerce?sslmode=require"
}

resource "google_secret_manager_secret" "redis_url" {
  secret_id = "omnicommerce-redis-url"

  replication {
    auto {}
  }
}

resource "google_secret_manager_secret_version" "redis_url" {
  secret      = google_secret_manager_secret.redis_url.id
  secret_data = "redis://${google_redis_instance.cache.host}:6379/0"
}

# ============================================================
# DNS
# ============================================================

resource "google_dns_record_set" "api" {
  name         = "api.${var.domain_name}."
  type         = "A"
  ttl          = 300
  managed_zone = data.google_dns_managed_zone.main.name
  rrdatas      = [google_compute_global_address.cdn.address]
}

resource "google_dns_record_set" "cdn" {
  name         = "cdn.${var.domain_name}."
  type         = "A"
  ttl          = 300
  managed_zone = data.google_dns_managed_zone.main.name
  rrdatas      = [google_compute_global_address.cdn.address]
}

data "google_dns_managed_zone" "main" {
  name = "omnicommerce-dns"
}

# ============================================================
# OUTPUTS
# ============================================================

output "gke_cluster_name" {
  value = google_container_cluster.gke.name
}

output "cloudsql_connection_name" {
  value     = google_sql_database_instance.postgres.connection_name
  sensitive = true
}

output "redis_host" {
  value     = google_redis_instance.cache.host
  sensitive = true
}

output "cdn_ip" {
  value = google_compute_global_address.cdn.address
}

output "artifact_registry" {
  value = google_artifact_registry_repository.docker.id
}

output "configure_kubectl" {
  value = "gcloud container clusters get-credentials ${google_container_cluster.gke.name} --region ${var.gcp_region}"
}
