{ config, lib, pkgs, ... }:
let
  cfg = config.clan.borgbackup;
in
{
  options.clan.borgbackup.destinations = lib.mkOption {
    type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
      options = {
        name = lib.mkOption {
          type = lib.types.str;
          default = name;
          description = "the name of the backup job";
        };
        repo = lib.mkOption {
          type = lib.types.str;
          description = "the borgbackup repository to backup to";
        };
        rsh = lib.mkOption {
          type = lib.types.str;
          default = "ssh -i ${config.clanCore.secrets.borgbackup.secrets."borgbackup.ssh".path} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null";
          description = "the rsh to use for the backup";
        };

      };
    }));
    default = { };
    description = ''
      destinations where the machine should be backuped to
    '';
  };

  imports = [ (lib.mkRemovedOptionModule [ "clan" "borgbackup" "enable" ] "Just define clan.borgbackup.destinations to enable it") ];

  config = lib.mkIf (cfg.destinations != { }) {
    services.borgbackup.jobs = lib.mapAttrs
      (_: dest: {
        paths = lib.flatten (map (state: state.folders) (lib.attrValues config.clanCore.state));
        exclude = [ "*.pyc" ];
        repo = dest.repo;
        environment.BORG_RSH = dest.rsh;
        compression = "auto,zstd";
        startAt = "*-*-* 01:00:00";
        persistentTimer = true;
        preHook = ''
          set -x
        '';

        encryption = {
          mode = "repokey";
          passCommand = "cat ${config.clanCore.secrets.borgbackup.secrets."borgbackup.repokey".path}";
        };

        prune.keep = {
          within = "1d"; # Keep all archives from the last day
          daily = 7;
          weekly = 4;
          monthly = 0;
        };
      })
      cfg.destinations;

    clanCore.secrets.borgbackup = {
      facts."borgbackup.ssh.pub" = { };
      secrets."borgbackup.ssh" = { };
      secrets."borgbackup.repokey" = { };
      generator.path = [ pkgs.openssh pkgs.coreutils pkgs.xkcdpass ];
      generator.script = ''
        ssh-keygen -t ed25519 -N "" -f "$secrets"/borgbackup.ssh
        mv "$secrets"/borgbackup.ssh.pub "$facts"/borgbackup.ssh.pub
        xkcdpass -n 4 -d - > "$secrets"/borgbackup.repokey
      '';
    };

    clanCore.backups.providers.borgbackup = {
      # TODO list needs to run locally or on the remote machine
      list = ''
        # we need yes here to skip the changed url verification
        ${lib.concatMapStringsSep "\n" (dest: ''yes y | borg-job-${dest.name} list --json | jq -r '. + {"job-name": "${dest.name}"}' '')
          (lib.attrValues cfg.destinations)}
      '';
      create = ''
        ${lib.concatMapStringsSep "\n" (dest: ''
          systemctl start borgbackup-job-${dest.name}
        '') (lib.attrValues cfg.destinations)}
      '';

      restore = ''
        set -efu
        cd /
        IFS=';' read -ra FOLDER <<< "$FOLDERS"
        yes y | borg-job-"$JOB" extract --list "$LOCATION"::"$ARCHIVE_ID" "''${FOLDER[@]}"
      '';
    };
  };
}
