{ pkgs, lib, config, ... }:
let
  inherit (builtins) attrNames listToAttrs readFile;
  inherit (lib) types;
  inherit (pkgs.lib) unlinesAttrs;
  inherit (config.security) gnupg;
  inherit (config.services) postfix rspamd dovecot2;
  redis = config.services.redis.servers.rspamd;
  inherit (config.users) users groups;
in
{
imports = [
  rspamd/autogeree.net.nix
  rspamd/sourcephile.fr.nix
];
options = {
  services.rspamd.dkimSelectorMap = lib.mkOption {
    type = types.lines;
    default = "";
    description = ''Each line maps a domain to its active DKIM selector'';
    apply = s: pkgs.writeText "dkim_selectors.map" s;
  };
};
config = {
users.groups.redis-rspamd.members = [ rspamd.user ];
users.groups.keys.members = [ rspamd.user ];
services.rspamd = {
  enable = true;
  debug = false;
  postfix.enable = postfix.enable;
  locals = {
    "dkim_signing.conf".text = ''
      selector_map = ${rspamd.dkimSelectorMap};
      path = "/run/keys/gnupg/rspamd/dkim/$domain/$selector.key/file";
      allow_username_mismatch = true;
    '';
    "arc.conf".text = ''
      selector_map = ${rspamd.dkimSelectorMap};
      path = "/run/keys/gnupg/rspamd/dkim/$domain/$selector.key/file";
      allow_username_mismatch = true;
    '';
    "redis.conf".text = ''
      servers = "${redis.unixSocket}";
      db = "1";
    '';
    "classifier-bayes.conf".text = ''
      users_enabled = false;
      backend = "redis";
      servers = "${redis.unixSocket}";
      database = "1";
      autolearn = true;
      cache {
        backend = "redis";
      }
      new_schema = true;
      expire = 86400;
      statfile {
        BAYES_HAM {
          spam = false;
        }
        BAYES_SPAM {
          spam = true;
        }
      }
    '';
    /*
    "logging.conf" = ''
      debug_modules = [“dkim_signing”]
    '';
    */
  };
  overrides = {
    "milter_headers.conf".text = ''
      extended_spam_headers = true;
    '';
    "actions.conf".text = ''
      reject     = 15; # Reject when reaching this score
      add_header =  6; # Add header when reaching this score
      greylist   =  4; # Apply greylisting when reaching this score (will emit `soft reject action`)
    '';
  };
  workers = {
    learner = {
      # Like controller but without a password, only the bindSockets' permissions
      type = "controller";
      includes = [ "$CONFDIR/worker-controller.inc" ];
      bindSockets = [
        { socket = "/run/rspamd/learner.sock";
          mode = "0660";
          owner = "${rspamd.user}";
          group = "${dovecot2.group}";
        }
      ];
      extraConfig = ''
      '';
    };
    controller = {
      includes = [
        "$CONFDIR/worker-controller.inc"
        gnupg.secrets."rspamd/controller/hashedPassword".path
      ];
      bindSockets = [
        "127.0.0.1:11334"
      ];
      extraConfig = ''
        #count = 1;
        #static_dir = "''${WWWDIR}";
      '';
    };
  };
};
security.gnupg.secrets."rspamd/controller/hashedPassword" = {
  # Generated with: rspamadm pw
  user = rspamd.user;
  pipe = ''${pkgs.gnused}/bin/sed -e 's/.*/password = "\0";/' '';
  systemdConfig.postStart = "systemctl try-restart --no-block rspamd"; # rspamd does not support reloading so far
};
systemd.services.rspamd = {
  wants = [ gnupg.secrets."rspamd/controller/hashedPassword".service ];
  after = [ gnupg.secrets."rspamd/controller/hashedPassword".service ];
};

fileSystems."/var/lib/redis-rspamd" = {
  device = "rpool/var/redis-rspamd";
  fsType = "zfs";
};
services.sanoid.datasets."rpool/var/redis-rspamd" = {
  use_template = [ "snap" ];
  daily = 7;
  monthly = 0;
};

services.redis.vmOverCommit = true;
services.redis.servers.rspamd = {
  enable = true;
  databases = 16;
  syslog = true;
  save = [ [1800 100] [300 1000] ];
  #unixSocketPerm = "660";
  settings = {
    maxmemory = "64MB";
    maxmemory-policy = "volatile-ttl";
  };
};
/*
services.postfix.extraConfig = ''
  smtpd_milters = unix:/run/rspamd.sock
  milter_default_action = accept
'';
# Allow users to run 'rspamc' and 'rspamadm'.
environment.systemPackages = [ pkgs.rspamd ];
*/
};
}