resource "kubernetes_secret" "mail_crypt_certs" {
  metadata {
    name      = "mail-crypt-certs"
    namespace = kubernetes_namespace.mail.metadata[0].name
  }
  data = {
    "ecprivkey.pem" = var.mail_crypt_private_key
    "ecpubkey.pem"  = var.mail_crypt_public_key
  }
  type = "Opaque"
}

resource "kubernetes_secret" "dovecot_users" {
  metadata {
    name      = "dovecot-users"
    namespace = kubernetes_namespace.mail.metadata[0].name
  }
  data = {
    "users" = local.dovecot_users
  }
}

resource "kubernetes_config_map" "dovecot_config" {
  metadata {
    name      = "dovecot-config"
    namespace = kubernetes_namespace.mail.metadata[0].name
  }

  data = {
    "dovecot.conf" = local.dovecot_config
  }
}

resource "kubernetes_config_map" "dovecot_sieve" {
  metadata {
    name      = "dovecot-sieve"
    namespace = kubernetes_namespace.mail.metadata[0].name
  }

  data = {
    "sieve" = local.dovecot_sieve
  }
}


resource "kubernetes_deployment" "dovecot" {
  metadata {
    namespace = kubernetes_namespace.mail.metadata[0].name
    name      = "dovecot"
    labels = {
      app = "dovecot"
    }
  }
  spec {
    replicas = 1
    selector {
      match_labels = {
        app = "dovecot"
      }
    }
    strategy {
      type = var.dovecot_use_host_networking ? "Recreate" : "RollingUpdate"
    }
    template {
      metadata {
        labels = {
          app = "dovecot"
        }
        annotations = {
          "checksum/dovecot" = local.dovecot_config_checksum
          "checksum/sieve"   = local.dovecot_sieve_checksum
          "checksum/stunnel" = local.dovecot_stunnel_config_checksum
          # Commented out to avoid unnecessary restarts
          # "checksum/users"   = local.dovecot_users_checksum
        }
      }
      spec {
        service_account_name = kubernetes_service_account.mail_app.metadata[0].name
        container {
          name  = "dovecot"
          image = "dovecot/dovecot:${var.dovecot_tag}"
          port {
            container_port = 31993
            host_port      = var.dovecot_use_host_networking ? 993 : null
          }
          port {
            name           = "lmtp"
            container_port = 31024
          }
          volume_mount {
            name       = "email-storage"
            mount_path = "/var/mail"
          }
          volume_mount {
            name       = "users"
            mount_path = "/etc/dovecot/users"
            sub_path   = "users"
            read_only  = true
          }
          volume_mount {
            name       = "dovecot-config"
            mount_path = "/etc/dovecot/dovecot.conf"
            sub_path   = "dovecot.conf"
            read_only  = true
          }
          volume_mount {
            name       = "dovecot-sieve"
            mount_path = "/etc/dovecot/sieve/default.sieve"
            sub_path   = "sieve"
            read_only  = true
          }
          volume_mount {
            name       = "certs"
            mount_path = "/etc/letsencrypt"
            read_only  = true
          }
          volume_mount {
            name       = "mail-crypt-certs"
            mount_path = "/etc/mail-crypt"
            read_only  = true
          }
          volume_mount {
            name       = "dovecot-logs"
            mount_path = "/var/log/dovecot"
            read_only  = false
          }
          volume_mount {
            name       = "tmp"
            mount_path = "/tmp"
          }
          volume_mount {
            name       = "dovecot-run"
            mount_path = "/var/run/dovecot"
          }
        }
        container {
          name  = "stunnel"
          image = "chainguard/stunnel:${local.stunnel_tag}"
          args  = ["/etc/conf/stunnel.conf"]
          volume_mount {
            name       = "stunnel-config"
            mount_path = "/etc/conf"
            read_only  = true
          }
          volume_mount {
            name       = "stunnel-certs"
            mount_path = "/etc/ssl/certs/private"
            read_only  = true
          }
          port {
            name           = "auth"
            container_port = 31000
          }
        }
        volume {
          name = "email-storage"
          host_path {
            path = local.mailboxes_path
          }
        }
        volume {
          name = "users"
          secret {
            secret_name = kubernetes_secret.dovecot_users.metadata[0].name
          }
        }
        volume {
          name = "dovecot-config"
          config_map {
            name = kubernetes_config_map.dovecot_config.metadata[0].name
          }
        }
        volume {
          name = "certs"
          secret {
            secret_name = "mail-tls"
          }
        }
        volume {
          name = "dovecot-sieve"
          config_map {
            name = kubernetes_config_map.dovecot_sieve.metadata[0].name
          }
        }
        volume {
          name = "mail-crypt-certs"
          secret {
            secret_name = kubernetes_secret.mail_crypt_certs.metadata[0].name
          }
        }
        volume {
          name = "stunnel-config"
          config_map {
            name = kubernetes_config_map.stunnel_dovecot.metadata[0].name
          }
        }
        volume {
          name = "stunnel-certs"
          secret {
            secret_name = kubernetes_manifest.stunnel_cert.manifest["metadata"]["name"]
            items {
              key  = "tls.crt"
              path = "tls.crt"
            }
            items {
              key  = "tls.key"
              path = "tls.key"
            }
          }
        }
        volume {
          name = "dovecot-logs"
          host_path {
            path = "/var/log/dovecot"
          }
        }
        volume {
          name = "tmp"
          empty_dir {}
        }
        volume {
          name = "dovecot-run"
          empty_dir {}
        }
      }
    }
  }
  depends_on = [kubernetes_manifest.mail_certificate, kubernetes_service_account.mail_app]
  lifecycle {
    ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
  }
}

resource "kubernetes_service" "dovecot" {
  metadata {
    namespace = kubernetes_namespace.mail.metadata[0].name
    name      = "imap"
  }

  spec {
    selector = {
      app = "dovecot"
    }

    port {
      name        = "imap"
      port        = 993
      target_port = 31993
    }

    type = "ClusterIP"
  }

  lifecycle {
    ignore_changes = [
      metadata[0].annotations
    ]
  }
}

resource "kubernetes_service" "dovecot_lmtp" {
  metadata {
    name      = "lmtp"
    namespace = kubernetes_namespace.mail.metadata[0].name
  }

  spec {
    selector = {
      app = "dovecot"
    }
    port {
      name        = "lmtp"
      port        = 31024
      target_port = 31024
    }
    type = "ClusterIP"
  }
}

resource "kubernetes_service" "dovecot_auth" {
  metadata {
    name      = "auth"
    namespace = kubernetes_namespace.mail.metadata[0].name
  }

  spec {
    selector = {
      app = "dovecot"
    }
    port {
      name        = "auth"
      port        = 31000
      target_port = 31000
    }
    type = "ClusterIP"
  }
}
