{
  config,
  lib,
  pkgs,
  ...
}: let
  inherit (builtins) listToAttrs getAttr;
  inherit (lib.modules) mkIf mkMerge;
  inherit (lib.options) mkOption mkEnableOption mdDoc;
  inherit (lib.strings) optionalString;
  inherit (lib.attrsets) attrValues;
  inherit (lib) types;

  cfg = config.services.postgreSQLRemoteBackup;
in {
  options = {
    # TODO: add host, port, user options
    services.postgreSQLRemoteBackup = {
      enable = mkEnableOption (mdDoc "PostgreSQL database dumps");

      keepPrev = mkOption {
        default = true;
        type = types.bool;
        description = mdDoc ''
          Keep the previous run's backups but rename them to $name.prev
        '';
      };

      startAt = mkOption {
        default = "4h";
        type = with types; either (listOf str) str;
        description = mdDoc ''
          This option defines (see `systemd.time` for format) when the
          databases should be dumped.
          The default is run every 4 hours.
        '';
      };

      backupUser = mkOption {
        default = "root";
        type = types.str;
        description = mdDoc ''
          User which will be used for backup job and files
        '';
      };

      databases = mkOption {
        default = [];
        type = types.listOf types.str;
        description = mdDoc ''
          List of database names to dump.
        '';
      };

      location = mkOption {
        default = "/var/backup/postgresql";
        type = types.path;
        description = mdDoc ''
          Path of directory where the PostgreSQL database dumps will be placed.
        '';
      };

      pgdumpOptions = mkOption {
        type = types.separatedString " ";
        default = "-C";
        description = mdDoc ''
          Command line options for pg_dump.
        '';
      };

      compression = mkOption {
        type = types.enum ["none" "zstd"];
        default = "zstd";
        description = mdDoc ''
          The type of compression to use on the generated database dump.
        '';
      };

      compressionLevel = mkOption {
        type = types.int;
        default = 9;
        description = mdDoc ''
          The compression level used when compression is enabled.
          zstd accepts levels 1 to 19.
        '';
      };
    };
  };

  config = mkMerge [
    (mkIf cfg.enable {
      systemd.tmpfiles.rules = [
        "d '${cfg.location}' 0700 ${cfg.backupUser} - - -"
      ];
    })
    (mkIf cfg.enable {
      systemd.services = listToAttrs (map (db: {
          name = "remotePostgreSQLBackup-${db}";
          value = let
            compressSuffixes = {
              "none" = "";
              "zstd" = ".zstd";
            };
            compressSuffix = getAttr cfg.compression compressSuffixes;

            compressCmd = getAttr cfg.compression {
              "none" = "cat";
              "zstd" = "${pkgs.zstd}/bin/zstd -c -${toString cfg.compressionLevel}";
            };

            mkSqlPath = prefix: suffix: "${cfg.location}/${db}${prefix}.sql${suffix}";
            curFile = mkSqlPath "" compressSuffix;
            prevFile = mkSqlPath ".prev" compressSuffix;
            prevFiles = map (mkSqlPath ".prev") (attrValues compressSuffixes);
            inProgressFile = mkSqlPath ".in-progress" compressSuffix;
          in {
            enable = true;

            description = "Backup of ${db} database(s)";

            requires = mkIf config.services.postgresql.enable [
              "postgresql.service"
            ];

            path = [
              pkgs.coreutils
              (let
                pgCfg = config.services.postgresql;
              in
                if pgCfg.enable
                then pgCfg.package
                else pkgs.postgresql)
            ];

            script = ''
              set -e -o pipefail

              umask 0077 # ensure backup is only readable by backup user

              ${optionalString cfg.keepPrev ''
                if [ -e ${curFile} ]; then
                  rm -f ${toString prevFiles}
                  mv ${curFile} ${prevFile}
                fi
              ''}

              pg_dump ${cfg.pgdumpOptions} ${db} \
                | ${compressCmd} \
                > ${inProgressFile}

              mv ${inProgressFile} ${curFile}
            '';

            serviceConfig = {
              Type = "oneshot";
              User = cfg.backupUser;
            };

            inherit (cfg) startAt;
          };
        })
        cfg.databases);
    })
  ];
}