{
  config,
  lib,
  pkgs,
  ...
}:

let
  inherit (lib)
    mkIf
    mkMerge
    readFile
    escapeShellArg
    ;

in
{
  imports = [ ./options.nix ];

  config = mkMerge [
    (mkIf
      (
        config.fediversity.garage.enable
        && config.fediversity.pixelfed.s3AccessKeyFile != null
        && config.fediversity.pixelfed.s3SecretKeyFile != null
      )
      {
        fediversity.garage = {
          ensureBuckets = {
            pixelfed = {
              website = true;
              # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want
              corsRules = {
                enable = true;
                allowedHeaders = [ "*" ];
                allowedMethods = [ "GET" ];
                allowedOrigins = [ "*" ];
              };
            };
          };

          ensureKeys = {
            pixelfed = {
              inherit (config.fediversity.pixelfed) s3AccessKeyFile s3SecretKeyFile;
              ensureAccess = {
                pixelfed = {
                  read = true;
                  write = true;
                  owner = true;
                };
              };
            };
          };
        };
      }
    )

    (mkIf config.fediversity.pixelfed.enable {
      ## NOTE: Pixelfed as packaged in nixpkgs has a permission issue that prevents Nginx
      ## from being able to serving the images. We fix it here, but this should be
      ## upstreamed. See https://github.com/NixOS/nixpkgs/issues/235147
      services.pixelfed.package = pkgs.pixelfed.overrideAttrs (old: {
        patches = (old.patches or [ ]) ++ [ ./group-permissions.patch ];
      });
      users.users.nginx.extraGroups = [ "pixelfed" ];

      services.pixelfed = {
        enable = true;
        domain = config.fediversity.pixelfed.domain;

        ## FIXME: secrets management; we should have a service that writes the
        ## `.env` file based on all the secrets that we need to put there.
        secretFile = pkgs.writeText "secrets.env" ''
          APP_KEY=adKK9EcY8Hcj3PLU7rzG9rJ6KKTOtYfA
          AWS_ACCESS_KEY_ID=${readFile config.fediversity.pixelfed.s3AccessKeyFile}
          AWS_SECRET_ACCESS_KEY=${readFile config.fediversity.pixelfed.s3SecretKeyFile}
        '';

        ## Taeer feels like this way of configuring Nginx is odd; there should
        ## instead be a `services.pixefed.nginx.enable` option and the actual Nginx
        ## configuration should be in `services.nginx`. See eg. `pretix`.
        ##
        ## TODO: If that indeed makes sense, upstream.
        nginx = {
          forceSSL = true;
          enableACME = true;
          # locations."/public/".proxyPass = "${config.fediversity.garage.web.urlForBucket "pixelfed"}/public/";
        };
      };

      services.pixelfed.settings = {
        ## NOTE: This depends on the targets, eg. universities might want control
        ## over who has an account. We probably want a universal
        ## `fediversity.openRegistration` option.
        OPEN_REGISTRATION = true;

        FILESYSTEM_CLOUD = "s3";
        PF_ENABLE_CLOUD = true;
        AWS_DEFAULT_REGION = "garage";
        AWS_URL = config.fediversity.garage.web.urlForBucket "pixelfed";
        AWS_BUCKET = "pixelfed";
        AWS_ENDPOINT = config.fediversity.garage.api.url;
        AWS_USE_PATH_STYLE_ENDPOINT = false;
      };

      ## Only ever run `pixelfed-data-setup` after `ensure-garage` has done its job.
      ## Otherwise, everything crashed dramatically.
      systemd.services.pixelfed-data-setup = {
        after = [ "ensure-garage.service" ];
      };

      networking.firewall.allowedTCPPorts = [
        80
        443
      ];

      systemd.services.inject-initial-pixelfed-user = {
        ## Make this service start after pixelfed has started successfully
        after = [ "phpfpm-pixelfed.service" ];
        requires = [ "phpfpm-pixelfed.service" ];

        serviceConfig = {
          Type = "simple";
          Restart = "on-failure";
          RestartSec = "10s";
          ExecStart = pkgs.writeShellScript "inject-initial-pixelfed-user.sh" ''
            #!/bin/sh
            set -euC

            ## NOTE: The packaging for Pixelfed provides a 'pixelfed-manage'
            ## command that is added to the environment but isn't easily
            ## grabable otherwise, so we go the ugly route and extract it from
            ## the Horizon service that runs 'pixelfed-manage horizon'.

            pixelfed-manage () {
              local f=${escapeShellArg config.systemd.services.pixelfed-horizon.serviceConfig.ExecStart}
              "''${f% horizon}" "$@"
            }

            ## NOTE: The 'user:table' command prints headers:
            ##
            ##   +----+----------+------+------------+
            ##   | ID | Username | Name | Registered |
            ##   +----+----------+------+------------+
            ##
            ## so we check whether that is all we got to know if there are any
            ## users yet.

            users_table=$(pixelfed-manage user:table)
            if [ "$(echo "$users_table" | wc -l)" -ne 3 ]; then
              printf 'There are already users; nothing to do:\n\n%s' "$users_table"
              exit 0
            fi

            ## No user so far; let's go!

            pixelfed-manage user:create \
              --name=${escapeShellArg config.fediversity.temp.initialUser.displayName} \
              --username=${escapeShellArg config.fediversity.temp.initialUser.username} \
              --email=${escapeShellArg config.fediversity.temp.initialUser.email} \
              --password="$(cat ${escapeShellArg config.fediversity.temp.initialUser.passwordFile})" \
              --confirm_email=1
          '';
        };

        # Set the service to automatically start
        wantedBy = [ "multi-user.target" ];
      };

    })
  ];
}