# Guide: https://nixos-mailserver.readthedocs.io/en/latest/setup-guide.html
{
  container,
  pkgs,
  util,
  const,
  lib,
  config,
  ...
}:
with lib;
let
  cfg = config.container.module.mail;
  domain = config.container.domain;
in
{
  options = {
    container.module.mail = {
      enable = mkEnableOption "Email server.";
      address = mkOption {
        default = "10.1.0.5";
        type = types.str;
      };
      port = mkOption {
        default = 80;
        type = types.int;
      };
      domain = mkOption {
        default = "mail.${config.container.domain}";
        type = types.str;
      };
      storage = mkOption {
        default = "${config.container.storage}/mail";
        type = types.str;
      };
    };
  };

  config = mkIf cfg.enable {
    systemd.tmpfiles.rules = container.mkContainerDir cfg [
      "data"
      # "data/indices"
      # "data/vmail"
      # "data/sieve"
      # "data/dkim"
    ];

    containers.mail = container.mkContainer cfg {
      bindMounts = {
        "/var/lib/dovecot/indices" = {
          hostPath = "${cfg.storage}/data/indices";
          isReadOnly = false;
        };
        "/var/vmail" = {
          hostPath = "${cfg.storage}/data/vmail";
          isReadOnly = false;
        };
        "/var/sieve" = {
          hostPath = "${cfg.storage}/data/sieve";
          isReadOnly = false;
        };
        "/var/dkim" = {
          hostPath = "${cfg.storage}/data/dkim";
          isReadOnly = false;
        };
        "/acme" = {
          hostPath = "${config.container.module.proxy.storage}/letsencrypt";
          isReadOnly = true;
        };
      };

      config =
        { config, ... }:
        container.mkContainerConfig cfg {
          imports = [
            (builtins.fetchTarball {
              url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-${const.stateVersion}/nixos-mailserver-nixos-${const.stateVersion}.tar.gz";
              sha256 = "sha256:0clvw4622mqzk1aqw1qn6shl9pai097q62mq1ibzscnjayhp278b";
            })
          ];

          mailserver = {
            enable = true;
            domains = [ domain ];
            fqdn = cfg.domain;
            sendingFqdn = domain;

            # Use `mkpasswd -sm bcrypt`.
            loginAccounts =
              let
                defaultQuota = "1G";
              in
              {
                "admin@${domain}" = {
                  name = "admin";
                  hashedPassword = "$2b$05$1O.dxXxaVshcBNybcqDRYuTlnYt3jDBwfPZWoDtP4BjOLoL0StYsi";
                  quota = defaultQuota;
                };
                "account@${domain}" = {
                  name = "account";
                  hashedPassword = "$2b$05$sCyZHdk98KqQ1qsTIvbrUeRJlNBOwBqDgpdc1QxiSnONlEkZ8xGNO";
                  quota = defaultQuota;
                };
                "hi@${domain}" = {
                  name = "hi";
                  hashedPassword = "$2b$05$6fT5hIhzIasNfp9IQr/ds.5RuxH95VKU3QJWlX3hmrAzDF3mExanq";
                  quota = defaultQuota;
                  aliases = [ "voronind@${domain}" ];
                };
                "job@${domain}" = {
                  name = "job";
                  hashedPassword = "$2b$05$.sUmv2.9EWPfLwJn/oZw2e1UbR7HrpNQ2THc5jjX3ysy7CY8ZWHUC";
                  quota = defaultQuota;
                };
                "trash@${domain}" = {
                  name = "trash";
                  hashedPassword = "$2b$05$kn5ygZjN9NR3LXjnKKRw/.DXaZQNW.1XEottlCFIoKiDpIj.JGLJm";
                  catchAll = [ domain ];
                  quota = defaultQuota;
                };
                "noreply@${domain}" = {
                  name = "noreply";
                  hashedPassword = "$2b$05$TaKwoYmcmkAhsRRv6xG5wOkChcz50cB9BP6QPUDKNAcxMbrY6AeMK";
                  sendOnly = true;
                  quota = defaultQuota;
                };
              };

            enableImap = true;
            enableImapSsl = true;
            enableSubmission = true;
            enableSubmissionSsl = true;

            enableManageSieve = true;
            virusScanning = false;

            certificateScheme = "manual";
            keyFile = "/acme/live/${domain}/privkey.pem";
            certificateFile = "/acme/live/${domain}/cert.pem";

            indexDir = "/var/lib/dovecot/indices";
            mailDirectory = "/var/vmail";
            sieveDirectory = "/var/sieve";
            dkimKeyDirectory = "/var/dkim";

            mailboxes = {
              All = {
                auto = "subscribe";
                specialUse = "All";
              };
              Archive = {
                auto = "subscribe";
                specialUse = "Archive";
              };
              Drafts = {
                auto = "subscribe";
                specialUse = "Drafts";
              };
              Junk = {
                auto = "subscribe";
                specialUse = "Junk";
                # autoexpunge = "3d";
              };
              Sent = {
                auto = "subscribe";
                specialUse = "Sent";
              };
              Trash = {
                auto = "subscribe";
                specialUse = "Trash";
                # autoexpunge = "30d";
              };
            };

            dmarcReporting = {
              inherit domain;
              enable = true;
              organizationName = "voronind";
              # email = "noreply@${domain}";
            };

            # monitoring = {
            #   enable = true;
            #   alertAddress = "admin@${domain}";
            # };
          };

          services = {
            roundcube = {
              enable = true;
              dicts = with pkgs.aspellDicts; [
                en
                ru
              ];
              hostName = cfg.domain;
              plugins = [ "managesieve" ];
              extraConfig = ''
                # starttls needed for authentication, so the fqdn required to match
                # the certificate
                # $config['smtp_server'] = "tls://${config.mailserver.fqdn}";
                # $config['smtp_server'] = "tls://localhost";
                $config['smtp_server'] = "localhost:25";
                $config['smtp_auth_type'] = null;
                $config['smtp_user'] = "";
                $config['smtp_pass'] = "";
                # $config['smtp_user'] = "%u";
                # $config['smtp_pass'] = "%p";
              '';
            };

            nginx = {
              virtualHosts.${cfg.domain} = {
                forceSSL = false;
                enableACME = false;
              };
            };
          };

          systemd = {
            services.autoexpunge = {
              description = "Delete old mail";
              serviceConfig.Type = "oneshot";
              path = [ pkgs.dovecot ];
              script = ''
                doveadm expunge -A mailbox Junk SENTBEFORE 7d
                doveadm expunge -A mailbox Trash SENTBEFORE 30d
                doveadm expunge -u trash@voronind.com mailbox Inbox SENTBEFORE 30d
                doveadm purge -A
              '';
            };

            timers.autoexpunge = {
              timerConfig = {
                OnCalendar = "daily";
                Persistent = true;
                Unit = "autoexpunge.service";
              };
              wantedBy = [ "timers.target" ];
            };
          };
        };
    };
  };
}