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

  makeNameSafe = name: builtins.replaceStrings [ "/" ] [ "-" ] name;

  daemonService = serve_config:
    lib.mkMerge [
      {
        wantedBy = [ "multi-user.target" ];

        after = [ "network.target" ];
        wants = [ "network.target" ];

        serviceConfig = {
          Type = "simple";
          Restart = "on-failure";
          RestartSec = "5s";

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

          ExecStart =
            "${pkgs.rclone}/bin/rclone serve ${serve_config.type} ${serve_config.remote} ${
              lib.concatStringsSep " " serve_config.extraArgs
            }";
        };
      }
      serve_config.serviceConfig
    ];
in {
  options = {
    services.rclone-serve = {
      enable = mkOption {
        type = types.bool;
        default = false;
      };

      remotes = mkOption {
        type = types.listOf (types.submodule {
          options = {
            remote = mkOption { type = types.str; };
            type = mkOption { type = types.str; };
            user = mkOption { type = types.str; };
            serviceConfig = mkOption { type = types.attrs; };

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

  config = mkMerge [
    (mkIf (cfg.enable && cfg.remotes != [ ]) {
      systemd.services = listToAttrs (map (remote: {
        name = "rclone-serve-${makeNameSafe remote.type}-${
            makeNameSafe remote.remote
          }";
        value = daemonService remote;
      }) cfg.remotes);
    })
  ];
}