{ lib, config, ... }:
let
  inherit (config.services) public-inbox;
  inherit (config.users) groups;
  orga = "sourcephile";
  domain = "${orga}.fr";
  repositories = [
    "doclang"
    "majurity"
    "reloto"
    "haskell/symantic"
    "haskell/symantic-atom"
    "haskell/symantic-base"
    "haskell/symantic-cli"
    "haskell/symantic-compta"
    "haskell/symantic-document"
    "haskell/symantic-http"
    "haskell/symantic-parser"
    "haskell/symantic-xml"
  ];
in
# Pour supprimer un message :
  # curl https://mails.sourcephile.fr/inbox/environnement/8ea699887ca47797b4460053588cbef2d115829ab4@vieber.ru/raw |
  # sudo -u public-inbox public-inbox-learn rm
{
  security.acme.certs."${domain}" = {
    postRun = "systemctl try-restart public-inbox-nntpd public-inbox-imapd";
  };
  networking.nftables.ruleset = ''
    table inet filter {
      chain input-net {
        tcp dport ${toString public-inbox.nntp.port} counter accept comment "public-inbox: NNTPS"
        tcp dport 1993 counter accept comment "public-inbox: IMAPS"
      }
      chain output-net {
      }
    }
  '';
  fileSystems."/var/lib/public-inbox" = {
    device = "rpool/var/public-inbox";
    fsType = "zfs";
  };
  systemd.services = {
    public-inbox-httpd = {
      confinement.enable = true;
      serviceConfig = {
        SupplementaryGroups = [ groups."git-daemon".name ];
        #BindReadOnlyPaths = [ "/var/lib/acme/${domain}" ];
      };
    };
    public-inbox-imapd = {
      confinement.enable = true;
      wants = [ "acme-selfsigned-${domain}.service" "acme-${domain}.service" ];
      after = [ "acme-selfsigned-${domain}.service" ];
      serviceConfig = {
        SupplementaryGroups = [ groups."acme".name ];
        BindReadOnlyPaths = [ "/var/lib/acme/${domain}" ];
      };
    };
    public-inbox-init = {
      confinement.enable = true;
    };
    public-inbox-nntpd = {
      confinement.enable = true;
      wants = [ "acme-selfsigned-${domain}.service" "acme-${domain}.service" ];
      after = [ "acme-selfsigned-${domain}.service" ];
      serviceConfig = {
        SupplementaryGroups = [ groups."acme".name ];
        BindReadOnlyPaths = [ "/var/lib/acme/${domain}" ];
      };
    };
  };
  services.public-inbox = {
    enable = true;
    postfix.enable = true;
    settings.publicinbox = {
      css = [ "href=https://mails.${domain}/style/light.css" ];
      nntpserver = [ "nntps://news.${domain}" ];
      wwwlisting = "match=domain";
      #imapserver = [ "mails.${domain}" ];
    };
    mda = {
      enable = true;
      args = [ "--no-precheck" ]; # Allow Bcc:
    };
    http = {
      enable = true;
      port = "/run/public-inbox-http.sock";
      #port = 8080;
      args = [ "-W0" ];
      mounts = [
        "https://mails.${domain}/inbox"
        "https://public-inbox.${domain}/inbox"
      ];
    };
    nntp = {
      enable = true;
      #port = 563;
      args = [ "-W0" ];
      cert = "/var/lib/acme/${domain}/fullchain.pem";
      key = "/var/lib/acme/${domain}/key.pem";
    };
    imap = {
      enable = true;
      # FIXME: find an IP or .onion to put 993
      port = null;
      args = [ "-W0" "--listen" "imaps://0.0.0.0:1993" ];
      #args = ["-W0"];
      cert = "/var/lib/acme/${domain}/fullchain.pem";
      key = "/var/lib/acme/${domain}/key.pem";
    };
    inboxes = {
      news = {
        address = [
          "news@${domain}"
        ];
        description = ''
          news@${domain} :
          annonces d'informations concernant importantes
        '';
        url = "https://mails.${domain}/inbox/news";
        newsgroup = "inbox.comp.${orga}.news";
        #coderepo = [ "sourcephile-txt" ];
      };
      chat = {
        address = [
          "chat@${domain}"
        ];
        description = ''
          chat@${domain} :
          discussions concernant l'informatique en général.
        '';
        url = "https://mails.${domain}/inbox/chat";
        newsgroup = "inbox.comp.${orga}.chat";
      };
      contact = {
        address = [
          "contact@${domain}"
        ];
        description = ''
          contact@${domain} :
          discussions avec le grand public.
        '';
        url = "https://mails.${domain}/inbox/contact";
        newsgroup = "inbox.comp.${orga}.contact";
        #coderepo = [ "${orga}" ];
      };
      environnement = {
        address = [
          "environnement@${domain}"
        ];
        description = ''
          environnement@${domain} :
          discussions sur les impacts environnementaux de l'informatique.
        '';
        url = "https://mails.${domain}/inbox/environnement";
        newsgroup = "inbox.comp.${orga}.environnement";
        #coderepo = [ "sourcephile-txt" ];
      };
      labo = {
        address = [
          "labo@${domain}"
        ];
        description = ''
          labo@${domain} :
          discussions concernant la science de l'informatique.
        '';
        url = "https://mails.${domain}/inbox/labo";
        newsgroup = "inbox.comp.${orga}.labo";
        # TODO: list many source code repositories
        #coderepo = [ "sourcephile-txt" ];
      };
      prod = {
        address = [
          "prod@${domain}"
        ];
        description = ''
          prod@${domain} :
          discussions concernant l'administration technique de l'infrastructure informatique.
        '';
        url = "https://mails.${domain}/inbox/prod";
        newsgroup = "inbox.comp.${orga}.prod";
        #coderepo = [ "sourcephile-txt" "sourcephile-nix" ];
      };
      orga = {
        address = [
          "orga@${domain}"
        ];
        description = ''
          orga@${domain} :
          discussions à l'attention de l'ensemble des personnes à bord.
        '';
        url = "https://mails.${domain}/inbox/orga";
        newsgroup = "inbox.comp.${orga}.orga";
        #coderepo = [ "sourcephile-txt" ];
      };
      test = {
        address = [
          "test@${domain}"
        ];
        description = ''
          test@${domain} :
          une cible de test pour effectuer des tirs de mails.
        '';
        url = "https://mails.${domain}/inbox/test";
        newsgroup = "inbox.comp.${orga}.test";
        hide = [ /* FIXME: doesn't work for IMAP */ "imap" "www" "manifest" ];
      };
    } // lib.genAttrs (map baseNameOf repositories) (name: {
      address = [
        "${name}@${domain}"
      ];
      description = ''
        ${name}@${domain} :
        discussions about ${name}.
      '';
      url = "https://mails.${domain}/inbox/${name}";
      newsgroup = "inbox.comp.${orga}.${name}";
      coderepo = [ name ];
    });
    settings.coderepo = {
      sourcephile-txt = {
        dir = "/var/lib/gitolite/repositories/sourcephile-txt.git";
        cgitUrl = "https://code.${domain}/sourcephile-txt.git";
      };
      sourcephile-nix = {
        dir = "/var/lib/gitolite/repositories/sourcephile-nix.git";
        cgitUrl = "https://code.${domain}/sourcephile-nix.git";
      };
    } // lib.listToAttrs (map
      (path: lib.nameValuePair (baseNameOf path) {
        dir = "/var/lib/gitolite/repositories/${path}.git";
        cgitUrl = "https://code.${domain}/${path}.git";
      })
      repositories);
  };
  services.sanoid.datasets."rpool/var/public-inbox" = {
    use_template = [ "snap" ];
    daily = 7;
  };
}