{
  config,
  lib,
  pkgs,
  ...
}:

let
  inherit (lib)
    escapeShellArgs
    filter
    hasPrefix
    makeBinPath
    mapAttrsToList
    mkEnableOption
    mkIf
    mkOption
    mkPackageOption
    optional
    optionals
    ;
  format = pkgs.formats.toml { };
in
{
  options =
    let
      inherit (lib.types)
        bool
        enum
        lines
        listOf
        str
        ;
    in
    {
      services.yggdrasil-jumper = {
        enable = mkEnableOption "the Yggdrasil Jumper system service";

        retrieveListenAddresses = mkOption {
          type = bool;
          default = true;
          description = ''
            Automatically retrieve listen addresses from the Yggdrasil router configuration.

            See `yggdrasil_listen` option in Yggdrasil Jumper configuration.
          '';
        };

        appendListenAddresses = mkOption {
          type = bool;
          default = true;
          description = ''
            Append Yggdrasil router configuration with listeners on loopback
            addresses (`127.0.0.1`) and preselected ports to support peering
            using client-server protocols like `quic` and `tls`.

            See `Listen` option in Yggdrasil router configuration.
          '';
        };

        detectWireguard = mkOption {
          type = bool;
          default = true;
          description = ''
            Control whether `settings.wireguard = true` should automatically
            provide CAP_NET_ADMIN capability and make the necessary packages
            available to Yggdrasil Jumper service.
          '';
        };

        settings = mkOption {
          type = format.type;
          default = { };
          example = {
            listen_port = 9999;
            whitelist = [ "<IPv6 address of a remote node>" ];
            wireguard = true;
          };
          description = ''
            Configuration for Yggdrasil Jumper as a Nix attribute set.
          '';
        };

        extraConfig = mkOption {
          type = lines;
          default = "";
          example = ''
            listen_port = 9999;
            whitelist = [
              "<IPv6 address of a remote node>"
            ];
          '';
          description = ''
            Configuration for Yggdrasil Jumper in plaintext.
          '';
        };

        package = mkPackageOption pkgs "yggdrasil-jumper" { };

        logLevel = mkOption {
          type = enum [
            "off"
            "error"
            "warn"
            "info"
            "debug"
            "trace"
          ];
          default = "info";
          description = ''
            Set logging verbosity for Yggdrasil Jumper.
          '';
        };

        extraArgs = mkOption {
          type = listOf str;
          default = [ ];
          description = ''
            Extra command line arguments for Yggdrasil Jumper.
          '';
        };
      };
    };

  config =
    let
      cfg = config.services.yggdrasil-jumper;

      wg = cfg.detectWireguard && (cfg.settings ? wireguard) && cfg.settings.wireguard;
      wgExtraPkgs = optionals wg (
        with pkgs;
        [
          iproute2
          iptables
          wireguard-tools
          conntrack-tools
        ]
      );

      # Generate, concatenate and validate config file
      jumperSettings = format.generate "yggdrasil-jumper-settings" cfg.settings;
      jumperExtraConfig = pkgs.writeText "yggdrasil-jumper-extra-config" cfg.extraConfig;
      jumperConfig = pkgs.runCommand "yggdrasil-jumper-config" { } ''
        export PATH="${makeBinPath wgExtraPkgs}:$PATH"
        cat ${jumperSettings} ${jumperExtraConfig} \
          | tee $out \
          | ${cfg.package}/bin/yggdrasil-jumper --validate --config -
      '';
    in
    mkIf cfg.enable {
      assertions = [
        {
          assertion = config.services.yggdrasil.enable;
          message = "`services.yggdrasil.enable` must be true for `yggdrasil-jumper` to operate";
        }
      ];

      services.yggdrasil.settings.Listen =
        let
          # By default linux dynamically allocates ports in range 32768..60999
          # `sysctl net.ipv4.ip_local_port_range`
          # See: https://xkcd.com/221/
          prot_port = {
            "tls" = 11814;
            "quic" = 11814;
          };
        in
        mkIf (cfg.retrieveListenAddresses && cfg.appendListenAddresses) (
          mapAttrsToList (prot: port: "${prot}://127.0.0.1:${toString port}") prot_port
        );

      services.yggdrasil-jumper.settings = {
        yggdrasil_admin_listen = [ "unix:///run/yggdrasil/yggdrasil.sock" ];
        yggdrasil_listen = mkIf cfg.retrieveListenAddresses (
          filter (a: !hasPrefix "tcp://" a) config.services.yggdrasil.settings.Listen
        );
      };

      systemd.services.yggdrasil-jumper = {
        description = "Yggdrasil Jumper Service";
        after = [ "yggdrasil.service" ];
        unitConfig.BindsTo = [ "yggdrasil.service" ];
        wantedBy = [ "multi-user.target" ];

        path = wgExtraPkgs;
        serviceConfig = {
          User = "yggdrasil";
          DynamicUser = true;

          # TODO: Remove this delay after support for proper startup notification lands in `yggdrasil-go`
          ExecStartPre = "${pkgs.coreutils}/bin/sleep 5";
          ExecStart = escapeShellArgs (
            [
              "${cfg.package}/bin/yggdrasil-jumper"
              "--loglevel"
              "${cfg.logLevel}"
              "--config"
              "${jumperConfig}"
            ]
            ++ cfg.extraArgs
          );
          KillSignal = "SIGINT";

          MemoryDenyWriteExecute = true;
          ProtectControlGroups = true;
          ProtectHome = "tmpfs";
          RestrictAddressFamilies = [
            "AF_UNIX"
            "AF_INET"
            "AF_INET6"
          ]
          ++ optional wg "AF_NETLINK";
          RestrictNamespaces = true;
          RestrictRealtime = true;
          AmbientCapabilities = optional wg "CAP_NET_ADMIN";
          CapabilityBoundingSet = optional wg "CAP_NET_ADMIN";
          SystemCallArchitectures = "native";
          SystemCallFilter = [
            "@system-service"
            "~@privileged"
          ];
        };
      };

      environment.systemPackages = [ cfg.package ];
    };

  meta.maintainers = with lib.maintainers; [ one-d-wide ];
}
