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

  networking.hostName = "mastodon";

  services = {
    backup = {
      enable = true;
      exclude = [ "/var/lib/mastodon/public-system/cache/" ];
      paths = [ "/var/lib/mastodon/" ];
    };

    # 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;
      enableBirdUITheme = 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";
      };
      ldap.enable = true;
      streamingProcesses = config.microvm.vcpu - 1;
      localDomain = "c3d2.social";
      otpSecretFile = config.sops.secrets."mastodon/otp-secret".path;
      secretKeyBaseFile = config.sops.secrets."mastodon/secret-key".path;
      sidekiqThreads = 40; # default 25 are just not doing it anymore, especially after issues
      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_16;
      upgrade.stopServices = [ "mastodon-sidekiq-all" "mastodon-streaming" "mastodon-web" ];
    };
  };

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

  systemd = {
    services = {
      fedifetcher = let
        configFormat = pkgs.formats.json {};
        configFile = configFormat.generate "fedifetcher.json" {
          server = "c3d2.social";
          home-timeline-length = 100;
          max-bookmarks = 5;
          max-favourites = 5;
          max-followers = 10;
          max-followings = 10;
          from-notifications = 10;
        };
      in rec {
        wants = [ "mastodon-web.service" ];
        after = wants;
        script = /* bash */ ''
          rm -f /var/lib/fedifetcher/lock.lock
          ${lib.getExe pkgs.fedifetcher} --config "${configFile}" --state-dir "/var/lib/fedifetcher/" \
            --access-token "$(cat ${config.sops.secrets."fedifetcher/access-tokens/1".path})" \
            --access-token "$(cat ${config.sops.secrets."fedifetcher/access-tokens/2".path})"
        '';
        serviceConfig = {
          User = config.services.mastodon.user;
          StateDirectory = "fedifetcher";
          WorkingDirectory = "%S/fedifetcher";
        };
      };

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

    timers.fedifetcher = {
      wantedBy = [ "timers.target" ];
      after = [ "network-online.target" ];
      timerConfig = {
        Persistent = true;
        OnBootSec = "10min";
        OnUnitActiveSec = "10min";
        Unit = "fedifetcher.service";
      };
    };
  };

  system.stateVersion = "22.11";
}
