{ config, lib, pkgs, ... }:
{
  c3d2.hq.statistics.enable = true;
  c3d2.deployment.server = "server10";
  microvm = {
    mem = 16 * 1024;
    vcpu = 16;
  };

  networking.hostName = "mastodon";

  services = {
    # Sidekiq monitoring
    collectd.plugins = {
      redis =
        let
          queries = [{
            command = "GET stat:processed";
            type = "counter";
            instance = "sidekiq_stat_processed";
          }
            {
              command = "GET stat:failed";
              type = "counter";
              instance = "sidekiq_stat_failed";
            }
            {
              command = "LLEN queue:#default";
              type = "queue_length";
              instance = "sidekiq_default_queue_len";
            }
            {
              command = "LLEN queue:#ingress";
              type = "queue_length";
              instance = "sidekiq_ingress_queue_len";
            }
            {
              command = "LLEN queue:#mailers";
              type = "queue_length";
              instance = "sidekiq_mailers_queue_len";
            }
            {
              command = "LLEN queue:#pull";
              type = "queue_length";
              instance = "sidekiq_pull_queue_len";
            }
            {
              command = "LLEN queue:#push";
              type = "queue_length";
              instance = "sidekiq_push_queue_len";
            }
            {
              command = "LLEN queue:#scheduler";
              type = "queue_length";
              instance = "sidekiq_scheduler_queue_len";
            }
            {
              command = "ZCARD schedule";
              type = "count";
              instance = "sidekiq_scheduled";
            }
            {
              command = "ZCARD retry";
              type = "count";
              instance = "sidekiq_retries";
            }
            {
              command = "ZCARD dead";
              type = "count";
              instance = "sidekiq_dead";
            }
            {
              command = "SCARD processes";
              type = "backends";
              instance = "sidekiq_processes";
            }];
        in
        ''
          <Node "mastodon">
            Host "${config.services.mastodon.redis.host}"
            Port "${toString config.services.mastodon.redis.port}"
            Timeout 3000

            ${lib.concatMapStrings ({ command, type, instance }: ''
              <Query "${command}">
                Type "${type}"
                Instance "${instance}"
              </Query>
            '') queries}
          </Node>
        '';
      postgresql = ''
        <Database "${config.services.mastodon.database.name}">
          Param database "${config.services.mastodon.database.name}"
          Query backends
          Query transactions
          Query queries
          Query disk_io
          Query disk_usage
        </Database>
      '';
    };

    elasticsearch = {
      enable = true;
      package = pkgs.elasticsearch7;
    };

    mastodon = {
      enable = true;
      configureNginx = true;
      elasticsearch.host = "127.0.0.1";
      extraConfig = {
        ALTERNATE_DOMAINS = lib.concatStringsSep "," config.services.nginx.virtualHosts.${config.services.mastodon.localDomain}.serverAliases;
        DEFAULT_LOCALE = "de";
        WEB_CONCURRENCY = toString config.microvm.vcpu;
        # MAX_THREADS = toString config.microvm.vcpu;
        LOG_LEVEL = "debug";

        LDAP_ENABLED = "true";
        LDAP_METHOD = "simple_tls";
        LDAP_HOST = "auth.c3d2.de";
        LDAP_PORT = "636";
        LDAP_BIND_DN = "uid=search,ou=users,dc=c3d2,dc=de";
        LDAP_BASE = "ou=users,dc=c3d2,dc=de";
        LDAP_SEARCH_FILTER = "(&(objectclass=person)(|(%{uid}=%{email})(%{mail}=%{email})))";
        LDAP_UID = "uid";
        # convert .,- (space) in LDAP usernames to underscore
        LDAP_UID_CONVERSION_ENABLED = "true";
      };
      localDomain = "c3d2.social";
      otpSecretFile = config.sops.secrets."mastodon/otp-secret".path;
      secretKeyBaseFile = config.sops.secrets."mastodon/secret-key".path;
      smtp = {
        host = "mail.c3d2.de";
        port = 587;
        fromAddress = "mail@c3d2.social";
        authenticate = false;
      };
      vapidPrivateKeyFile = config.sops.secrets."mastodon/vapid-private-key".path;
      vapidPublicKeyFile = config.sops.secrets."mastodon/vapid-public-key".path;
    };

    nginx.virtualHosts.${config.services.mastodon.localDomain}.serverAliases = [
      "${config.networking.hostName}.flpk.zentralwerk.org"
      "social.c3d2.de"
    ];

    portunus.addToHosts = true;

    postgresql = {
      enable = true;
      ensureUsers = [{
        name = "collectd";
        ensurePermissions = {
          "DATABASE \"${config.services.mastodon.database.name}\"" = "ALL PRIVILEGES";
        };
      }];
      package = pkgs.postgresql_15;
      upgrade.stopServices = [ "mastodon-sidekiq" "mastodon-streaming" "mastodon-web" ];
    };
  };

  sops = {
    defaultSopsFile = ./secrets.yaml;
    secrets."mastodon/env".owner = "mastodon";
    secrets."mastodon/otp-secret".owner = "mastodon";
    secrets."mastodon/secret-key".owner = "mastodon";
    secrets."mastodon/vapid-private-key".owner = "mastodon";
    secrets."mastodon/vapid-public-key".owner = "mastodon";
  };

  system.stateVersion = "22.11";

  # Inject LDAP secrets
  systemd.services.mastodon-init-dirs.script = lib.mkAfter ''
    cat ${config.sops.secrets."mastodon/env".path} >> /var/lib/mastodon/.secrets_env
  '';
}
