{
  config,
  lib,
  pkgs,
  ...
}:
with lib; let
  cfg = config.services.rclone-sync;

  daemonService = sync_config: {
    serviceConfig = lib.mkMerge [
      {
        Type = "oneshot";

        User =
          if cfg.user != null
          then "${cfg.user}"
          else "root";

        ExecStart = "${pkgs.rclone}/bin/rclone sync ${sync_config.source} ${sync_config.dest} ${lib.concatStringsSep " " sync_config.extraArgs} -P";
      }
      (lib.mkIf sync_config.autoRestart {
        TimeoutSec = 60;
        Restart = "on-failure";
      })

      sync_config.serviceConfig
    ];
  };
in {
  options = {
    services.rclone-sync = {
      enable = mkOption {
        type = types.bool;
        default = false;
      };

      user = mkOption {
        type = types.str;
        default = null;
      };

      sync_jobs = mkOption {
        type = types.listOf (types.submodule {
          options = {
            source = mkOption {type = types.str;};
            dest = mkOption {type = types.str;};
            id = mkOption {type = types.str;};

            extraArgs = mkOption {
              type = types.listOf types.str;
              default = [];
            };

            autoRestart = mkOption {
              type = types.bool;
              default = true;
            };

            timerConfig = mkOption {
              type = types.attrs;
              default = {
                OnStartupSec = "60";
                OnCalendar = "4h";
              };
            };
            serviceConfig = mkOption {
              type = types.attrs;
              default = {};
            };
          };
        });
        default = [];
      };
    };
  };

  config = mkMerge [
    (mkIf (cfg.enable && cfg.sync_jobs != []) {
      environment.systemPackages =
        [
          (pkgs.writeShellScriptBin "rclone-sync-all" (lib.concatStringsSep "\n" (map (
              job: ''
                ${pkgs.rclone}/bin/rclone sync ${job.source} ${job.dest} ${lib.concatStringsSep " " job.extraArgs} -P $@
              ''
            )
            cfg.sync_jobs)))
        ]
        ++ (
          map (
            job:
              pkgs.writeShellScriptBin "rclone-manual-sync-${job.id}" ''
                exec ${pkgs.rclone}/bin/rclone sync ${job.source} ${job.dest} ${lib.concatStringsSep " " job.extraArgs} -P $@
              ''
          )
          cfg.sync_jobs
        );

      systemd.services = listToAttrs (map (job: {
          name = "rclone-sync-${job.id}";
          value = daemonService job;
        })
        cfg.sync_jobs);

      systemd.timers = listToAttrs (map (job: let
          name = "rclone-sync-${job.id}";
        in {
          inherit name;
          value = {
            wantedBy = ["timers.target"];
            partOf = ["${name}.service"];
            timerConfig = job.timerConfig;
          };
        })
        cfg.sync_jobs);
    })
  ];
}