{ lib, config, ... }:
with lib;
let
  cfg = config.fudo.mail-server;
  container-maildir = "/var/lib/mail";
  container-statedir = "/var/lib/mail-state";
  container-shared = "container/mail-server";
  container-postfix-cert = "${container-shared}/postfix/cert.pem";
  container-postfix-key = "${container-shared}/postfix/key.pem";
  container-dovecot-cert = "${container-shared}/dovecot/cert.pem";
  container-dovecot-key = "${container-shared}/dovecot/key.pem";
  container-fudo-ca-cert = "${container-shared}/fudo-ca.pem";

  # Don't bother with group-id, nixos doesn't seem to use it anyway
  container-mail-user = "mailer";
  container-mail-user-id = 542;
  container-mail-group = "mailer";
  fudo-cfg = config.fudo.common;

in rec {
  options.fudo.mail-server.container = {
    ldap-url = mkOption {
      type = types.str;
      description = "URL of the LDAP server to use for authentication.";
      example = "ldaps://auth.fudo.org/";
    };
  };

  config = mkIf (cfg.enableContainer && !cfg.enable) {

    # Disable postfix on thi host--it'll be run in the container instead
    services.postfix.enable = false;

    # Copy data intended for the container to a path in /etc which can be
    # bind-mounted.
    environment.etc = {
      "${container-postfix-cert}" = {
        mode = "0444";
        source = cfg.postfix.ssl-certificate;
      };

      "${container-postfix-key}" = {
        mode = "0400";
        source = cfg.postfix.ssl-private-key;
      };

      "${container-dovecot-cert}" = {
        mode = "0444";
        source = cfg.dovecot.ssl-certificate;
      };

      "${container-dovecot-key}" = {
        mode = "0400";
        source = cfg.dovecot.ssl-private-key;
      };

      "${container-fudo-ca-cert}" = {
        mode = "0444";
        source = "/etc/nixos/static/fudo_ca.pem";
      };
    };

    security.acme.certs.${cfg.hostname}.email = fudo-cfg.admin-email;

    services.nginx = mkIf cfg.monitoring {
      enable = true;

      virtualHosts = let
        proxy-headers = ''
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header Host $host;
        '';
        trusted-network-string =
          optionalString ((length fudo-cfg.local-networks) > 0)
          (concatStringsSep "\n"
            (map (network: "allow ${network};") fudo-cfg.local-networks)) + ''

              deny all;'';

      in {
        "${cfg.hostname}" = {
          enableACME = true;
          forceSSL = true;

          locations."/metrics/postfix" = {
            proxyPass = "http://127.0.0.1:9154/metrics";

            extraConfig = ''
              ${proxy-headers}

              ${trusted-network-string}
            '';
          };

          locations."/metrics/dovecot" = {
            proxyPass = "http://127.0.0.1:9166/metrics";

            extraConfig = ''
              ${proxy-headers}

              ${trusted-network-string}
            '';
          };

          locations."/metrics/rspamd" = {
            proxyPass = "http://127.0.0.1:7980/metrics";

            extraConfig = ''
              ${proxy-headers}

              ${trusted-network-string}
            '';
          };
        };
      };
    };

    containers.mail-server = {

      autoStart = true;

      bindMounts = {
        "${container-maildir}" = {
          hostPath = cfg.mail-directory;
          isReadOnly = false;
        };

        "${container-statedir}" = {
          hostPath = cfg.state-directory;
          isReadOnly = false;
        };

        "/etc/${container-shared}" = {
          hostPath = "/etc/${container-shared}";
          isReadOnly = true;
        };
      };

      config = { config, pkgs, ... }: {

        environment.systemPackages = with pkgs; [ nmap ];

        imports = [ ./mail.nix ];

        environment = {
          etc = {
            "postfix-certs/key.pem" = {
              source = "/etc/${container-postfix-key}";
              user = config.services.postfix.user;
              mode = "0400";
            };

            "dovecot-certs/key.pem" = {
              source = "/etc/${container-dovecot-key}";
              user = config.services.dovecot2.user;
              mode = "0400";
            };
          };
        };

        fudo.mail-server = {
          enable = true;
          hostname = cfg.hostname;
          domain = cfg.domain;

          debug = cfg.debug;
          monitoring = cfg.monitoring;

          state-directory = container-statedir;
          mail-directory = container-maildir;

          postfix.ssl-certificate = "/etc/${container-postfix-cert}";
          postfix.ssl-private-key = "/etc/postfix-certs/key.pem";

          dovecot = {
            ssl-certificate = "/etc/${container-dovecot-cert}";
            ssl-private-key = "/etc/dovecot-certs/key.pem";
            ldap = {
              # ca = "/etc/${container-fudo-ca-cert}";
              server-urls = cfg.dovecot.ldap.server-urls;
              reader-dn = cfg.dovecot.ldap.reader-dn;
              reader-passwd = cfg.dovecot.ldap.reader-passwd;
            };
          };

          local-domains = cfg.local-domains;

          alias-users = cfg.alias-users;
          user-aliases = cfg.user-aliases;
          sender-blacklist = cfg.sender-blacklist;
          recipient-blacklist = cfg.recipient-blacklist;
          trusted-networks = cfg.trusted-networks;

          mail-user = container-mail-user;
          mail-user-id = container-mail-user-id;
          mail-group = container-mail-group;

          clamav.enable = cfg.clamav.enable;

          dkim.signing = cfg.dkim.signing;
        };
      };
    };
  };
}