{
  config,
  lib,
  pkgs,
  ...
}: let
  inherit (lib.modules) mkIf mkMerge;
  inherit (lib.options) mkOption;
  inherit (lib.strings) concatStringsSep;
  inherit (lib) types;
  inherit (builtins) listToAttrs;

  cfg = config.services.rclone-sync;

  daemonService = syncConfig: {
    serviceConfig = mkMerge [
      {
        Type = "oneshot";

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

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

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

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

      syncJobs = 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 = "1m";
                OnUnitActiveSec = "2h";
              };
            };
            serviceConfig = mkOption {
              type = types.attrs;
              default = {};
            };
          };
        });
        default = [];
      };
    };
  };

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

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

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