# PostgreSQL in Kubernetes Cluster
# Using StatefulSet with PersistentVolume for data persistence

# Kubernetes Secret for PostgreSQL
resource "kubernetes_secret" "postgresql" {
  metadata {
    name      = "postgresql-credentials"
    namespace = kubernetes_namespace.app.metadata[0].name
    labels    = local.common_labels
  }

  data = {
    POSTGRES_USER     = var.postgresql_admin_username
    POSTGRES_PASSWORD = var.postgresql_admin_password
    POSTGRES_DB       = local.postgresql_db_name
  }

  type = "Opaque"
}

# PersistentVolumeClaim for PostgreSQL data
resource "kubernetes_persistent_volume_claim" "postgresql" {
  metadata {
    name      = "postgresql-pvc"
    namespace = kubernetes_namespace.app.metadata[0].name
    labels    = local.common_labels
  }

  spec {
    access_modes = ["ReadWriteOnce"]

    resources {
      requests = {
        storage = "10Gi"
      }
    }
  }

  wait_until_bound = false
}

# PostgreSQL StatefulSet
resource "kubernetes_stateful_set" "postgresql" {
  metadata {
    name      = "postgresql"
    namespace = kubernetes_namespace.app.metadata[0].name
    labels    = local.common_labels
  }

  spec {
    service_name = "postgresql"
    replicas     = 1

    selector {
      match_labels = {
        app = "postgresql"
      }
    }

    template {
      metadata {
        labels = merge(
          local.common_labels,
          {
            app = "postgresql"
          }
        )
      }

      spec {
        container {
          name  = "postgresql"
          image = "postgres:16-alpine"

          port {
            container_port = 5432
            name           = "postgresql"
          }

          env_from {
            secret_ref {
              name = kubernetes_secret.postgresql.metadata[0].name
            }
          }

          volume_mount {
            name       = "postgresql-storage"
            mount_path = "/var/lib/postgresql/data"
            sub_path   = "postgres"
          }

          resources {
            requests = {
              cpu    = "250m"
              memory = "512Mi"
            }
            limits = {
              cpu    = "1000m"
              memory = "1Gi"
            }
          }

          liveness_probe {
            exec {
              command = ["pg_isready", "-U", var.postgresql_admin_username]
            }
            initial_delay_seconds = 30
            period_seconds        = 10
            timeout_seconds       = 5
            failure_threshold     = 3
          }

          readiness_probe {
            exec {
              command = ["pg_isready", "-U", var.postgresql_admin_username]
            }
            initial_delay_seconds = 5
            period_seconds        = 5
            timeout_seconds       = 3
            failure_threshold     = 3
          }
        }

        volume {
          name = "postgresql-storage"
          persistent_volume_claim {
            claim_name = kubernetes_persistent_volume_claim.postgresql.metadata[0].name
          }
        }
      }
    }
  }

  depends_on = [
    kubernetes_persistent_volume_claim.postgresql,
    kubernetes_secret.postgresql
  ]
}

# PostgreSQL Service
resource "kubernetes_service" "postgresql" {
  metadata {
    name      = "postgresql"
    namespace = kubernetes_namespace.app.metadata[0].name
    labels    = local.common_labels
  }

  spec {
    selector = {
      app = "postgresql"
    }

    port {
      name        = "postgresql"
      port        = 5432
      target_port = 5432
      protocol    = "TCP"
    }

    type             = "ClusterIP"
    cluster_ip       = "None" # Headless service for StatefulSet
    session_affinity = "None"
  }

  depends_on = [
    kubernetes_stateful_set.postgresql
  ]
}
