{
  config,
  lib,
  pkgs,
  options,
  ...
}:
let
  inherit (lib)
    mkIf
    mkEnableOption
    mkOption
    concatStringsSep
    toList
    listToAttrs
    ;
  inherit (lib.types)
    listOf
    nonEmptyStr
    package
    str
    port
    bool
    submoduleWith
    ;
  inherit (lib.my) slugify;
  cfg = config.modules.services.rsync-backup;
in
{
  # Used to back up multiple source destinations to a target destination regularly,
  # with possibility to enable incremental backups for versioning.

  # TODO: systemd unit
  # - [x] script taking configurable args
  # - [x] sync from/to paths
  # - [ ] support
  #       - [ ] nfs
  #       - [ ] sftp
  #       - [ ] ssh
  #       - [x] local
  #       - [x] rsyncd
  # - [ ] retention limit for incremental backups

  options.modules.services.rsync-backup = {
    enable = mkEnableOption "rsync backups";

    modules = mkOption {
      default = [ ];
      type = listOf (submoduleWith {
        shorthandOnlyDefinesConfig = true;
        modules = toList (import ./module.nix);
        specialArgs = {
          rootCfg = cfg;
        };
      });
    };

    exclude = mkOption {
      type = listOf str;
      default = [ ".git" ];
    };

    followGitignore = mkOption {
      type = bool;
      default = true;
    };

    package = mkOption {
      type = package;
      default = pkgs.rsync;
      description = ''
        The rsync package to use.
      '';
    };

    interval = mkOption {
      type = nonEmptyStr;
      default = "daily";
    };

    unitName = mkOption {
      type = nonEmptyStr;
      default = "rsync-backup";
    };

    port = mkOption {
      type = port;
      default = options.modules.server.rsync-daemon.port.default;
    };
  };

  config = mkIf cfg.enable {
    systemd.timers = listToAttrs (
      map (
        mod:
        let
          name = "${cfg.unitName}-${slugify mod.target.location}";
        in
        {
          inherit name;
          value = {
            enable = true;
            wantedBy = [ "timers.target" ];
            unitConfig = {
              Description = "Triggers rsync-backups regularly.";
            };
            timerConfig = {
              Unit = "${name}.service";
              OnCalendar = mod.interval;
              Persistent = true;
            };
          };
        }
      ) cfg.modules
    );

    systemd.services = listToAttrs (
      map (mod: {
        name = "${cfg.unitName}-${slugify mod.target.location}";
        value = {
          script =
            let
              destination =
                if mod.incremental.enable then "${mod.target.finalLocation}/backup" else mod.target.finalLocation;
              sources = concatStringsSep " " (map (s: "\"${s}\"") mod.sources);
            in
            ''
              ${cfg.package}/bin/rsync \
                  ${mod.flagsFinal} \
                  ${sources} \
                  "${destination}"
            '';

          requires = mkIf (mod.target.type == "rsyncd") [ "network.target" ];
          unitConfig = {
            Description = "Backs up files from a source location to a specified destination.";
          };
          serviceConfig = {
            Type = "simple";
            Restart = "on-failure";
            RestartSec = 300;
            PrivateDevices = true;
            PrivateTmp = true;
            ProtectSystem = "full";
            ReadOnlyPaths = concatStringsSep " " mod.sources;
            IPAddressAllow = "any";
          };
        };
      }) cfg.modules
    );
  };
}
