locals {
  gitea_env_vars = {
    APP_NAME                 = "A13Labs git repository"
    HTTP_PORT                = "3000"
    RUN_MODE                 = "prod"
    LFS_START_SERVER         = "true"
    SSH_DOMAIN               = local.gitea_fqdn
    DISABLE_REGISTRATION     = true
    INSTALL_LOCK             = "true"
    DB_TYPE                  = "mysql"
    DB_NAME                  = "gitea"
    DB_HOST                  = module.gitea_database.host
    SSH_LISTEN_PORT          = 22
    GITEA__mailer__ENABLED   = true
    GITEA__mailer__FROM      = "gitea@alexpires.me"
    GITEA__mailer__SMTP_ADDR = local.scaleway_smtp_host
    GITEA__mailer__SMTP_PORT = local.scaleway_smtp_port
    GITEA__mailer__PROTOCOL  = "smtps"
  }

  gitea_secrets = {
    DB_USER = {
      key  = "username"
      name = module.gitea_database.app_crendentials_name
    }
    DB_PASSWD = {
      key  = "password"
      name = module.gitea_database.app_crendentials_name
    }
    GITEA__mailer__USER = {
      key  = "username"
      name = kubernetes_secret.gitea_mail_credentials.metadata[0].name
    }
    GITEA__mailer__PASSWD = {
      key  = "password"
      name = kubernetes_secret.gitea_mail_credentials.metadata[0].name
    }
  }

  gitea_path        = "${local.persistent_folder}/gitea"
  gitea_db_path     = "${local.database_folder}/mysql.gitea"
  gitea_backup_path = "${local.persistent_folder}/backup.gitea"
}

#
# Namespace
#
resource "kubernetes_namespace" "gitea" {
  metadata {
    annotations = {
      name = "gitea"
    }

    labels = {
      name = "gitea"
    }

    name = "gitea"
  }
}

#
# Mail credentials
#
resource "kubernetes_secret" "gitea_mail_credentials" {
  metadata {
    name      = "gitea-mail-credentials"
    namespace = kubernetes_namespace.gitea.metadata[0].name
  }
  data = {
    username = var.scaleway_project_id
    password = scaleway_iam_api_key.mail_app_api.secret_key
  }
  type = "Opaque"
}

#
# Setup MariaDB database
#
module "gitea_database" {
  source = "./modules/k8s_mariadb"

  namespace = kubernetes_namespace.gitea.metadata[0].name
  app_name  = "gitea"

  app_password  = var.gitea_mysql_password
  root_password = var.mysql_root_password

  retention_days = local.local_backup_retention_days
  cron_schedule  = local.gitea_sql_backup_cron_schedule

  database_folder = local.gitea_db_path
  backup_folder   = local.gitea_backup_path
}

#
# Setup rsync backup job to scaleway bucket
#
module "gitea_backup" {
  source = "./modules/scw_backup_job"

  namespace = kubernetes_namespace.gitea.metadata[0].name
  app_name  = "gitea"

  scaleway_organization_id = var.scaleway_organization_id
  scaleway_project_id      = var.scaleway_organization_id
  access_key               = scaleway_iam_api_key.backup_app_api.access_key
  secret_key               = scaleway_iam_api_key.backup_app_api.secret_key
  bucket_name              = scaleway_object_bucket.backup.name

  retention_days = local.local_backup_retention_days
  cron_schedule  = local.gitea_files_backup_cron_schedule

  source_folder = local.gitea_path
  target_folder = local.gitea_backup_path
}

# 
# Gitea service, ingress, deployment and file backup job
#
resource "kubernetes_service_account" "gitea_service_account" {

  metadata {
    name      = "gitea-app-sa"
    namespace = kubernetes_namespace.gitea.metadata[0].name
  }

  automount_service_account_token = false
}

resource "kubernetes_service" "gitea_http" {
  metadata {
    name      = "http"
    namespace = kubernetes_namespace.gitea.metadata[0].name
  }
  spec {
    port {
      port        = 80
      target_port = "http"
    }
    selector = {
      app = "gitea"
    }
    cluster_ip = "None"
  }
}

resource "kubernetes_ingress_v1" "gitea_ingress" {
  metadata {
    name      = "gitea-ingress"
    namespace = kubernetes_namespace.gitea.metadata[0].name

    annotations = {
      "kubernetes.io/ingress.class"                         = "public"
      "cert-manager.io/cluster-issuer"                      = "letsencrypt-prod"
      "nginx.ingress.kubernetes.io/ssl-redirect"            = "true"
      "nginx.ingress.kubernetes.io/proxy-body-size"         = "8m"
      "nginx.ingress.kubernetes.io/proxy-request-buffering" = "on"
      "nginx.ingress.kubernetes.io/proxy-buffer-size"       = "32k"
      "nginx.ingress.kubernetes.io/proxy-buffers-number"    = "16"
    }
  }
  spec {
    tls {
      hosts       = [local.gitea_fqdn]
      secret_name = "gitea-tls"
    }
    rule {
      host = local.gitea_fqdn
      http {
        path {
          backend {
            service {
              name = "http"
              port {
                number = 80
              }
            }
          }
        }
      }
    }
  }
}

resource "kubernetes_deployment" "gitea" {

  depends_on = [module.gitea_database]

  metadata {
    name      = "gitea-app"
    namespace = kubernetes_namespace.gitea.metadata[0].name
  }
  spec {
    selector {
      match_labels = {
        app = "gitea"
      }
    }
    strategy {
      type = "Recreate"
    }
    template {
      metadata {
        labels = {
          app = "gitea"
        }
      }
      spec {
        service_account_name = kubernetes_service_account.gitea_service_account.metadata[0].name
        container {
          name              = "gitea"
          image             = "gitea/gitea:${local.gitea_version}"
          image_pull_policy = "Always"

          resources {
            requests = {
              memory = "100Mi"
            }
            limits = {
              memory = "300Mi"
            }
          }

          liveness_probe {
            http_get {
              path = "/api/healthz"
              port = "http"
            }
            initial_delay_seconds = 200
            period_seconds        = 300
            success_threshold     = 1
            failure_threshold     = 5
          }

          readiness_probe {
            tcp_socket {
              port = "http"
            }
            initial_delay_seconds = 5
            period_seconds        = 10
            success_threshold     = 1
            failure_threshold     = 3
          }

          dynamic "env" {
            for_each = local.gitea_env_vars
            content {
              name  = env.key
              value = env.value
            }
          }
          security_context {
            allow_privilege_escalation = false
          }

          dynamic "env" {
            for_each = local.gitea_secrets
            content {
              name = env.key
              value_from {
                secret_key_ref {
                  key  = env.value.key
                  name = env.value.name
                }
              }
            }
          }

          port {
            container_port = 3000
            name           = "http"
          }
          port {
            container_port = 22
            name           = "ssh"
          }

          volume_mount {
            mount_path = "/data"
            name       = "persistent-storage"
          }
        }
        volume {
          name = "persistent-storage"
          host_path {
            path = local.gitea_path
          }
        }
      }
    }
  }
}

resource "kubernetes_role" "gitea_ssh_access" {
  metadata {
    name      = "gitea-ssh-access"
    namespace = kubernetes_namespace.gitea.metadata[0].name
  }
  rule {
    api_groups = [""]
    resources  = ["pods", "pods/log"]
    verbs      = ["get", "list"]
  }
  rule {
    api_groups = [""]
    resources  = ["pods/exec"]
    verbs      = ["create"]
  }
}

resource "kubernetes_role_binding" "gitea_ssh_access" {
  metadata {
    name      = "gitea-ssh-access"
    namespace = kubernetes_namespace.gitea.metadata[0].name
  }
  role_ref {
    api_group = "rbac.authorization.k8s.io"
    kind      = "Role"
    name      = kubernetes_role.gitea_ssh_access.metadata[0].name
  }
  subject {
    kind      = "ServiceAccount"
    name      = kubernetes_service_account.gitea_service_account.metadata[0].name
    namespace = kubernetes_namespace.gitea.metadata[0].name
  }
}

resource "kubernetes_secret" "gitea_access_token" {
  metadata {
    annotations = {
      "kubernetes.io/service-account.name" = kubernetes_service_account.gitea_service_account.metadata[0].name
    }
    name      = "git-token"
    namespace = kubernetes_namespace.gitea.metadata[0].name
  }

  type                           = "kubernetes.io/service-account-token"
  wait_for_service_account_token = true
}
