{
  config,
  lib,
  pkgs,
  ...
}:
let
  cfg = config.networking.networkmanager;
  toml = pkgs.formats.toml { };

  enabled = (lib.length cfg.ensureProfiles.secrets.entries) > 0;

  nmFileSecretAgentConfig = {
    entry = builtins.map (
      i:
      {
        key = i.key;
        file = i.file;
      }
      // lib.optionalAttrs (i.matchId != null) { match_id = i.matchId; }
      // lib.optionalAttrs (i.matchUuid != null) { match_uuid = i.matchUuid; }
      // lib.optionalAttrs (i.matchType != null) { match_type = i.matchType; }
      // lib.optionalAttrs (i.matchIface != null) { match_iface = i.matchIface; }
      // lib.optionalAttrs (i.matchSetting != null) {
        match_setting = i.matchSetting;
      }
    ) cfg.ensureProfiles.secrets.entries;
  };
  nmFileSecretAgentConfigFile = toml.generate "config.toml" nmFileSecretAgentConfig;
in
{
  meta = {
    maintainers = [ lib.maintainers.lilioid ];
  };

  ####### interface
  options = {
    networking.networkmanager.ensureProfiles.secrets = {
      package = lib.mkPackageOption pkgs "nm-file-secret-agent" { };
      entries = lib.mkOption {
        description = ''
          A list of secrets to provide to NetworkManager by reading their values from configured files.

          Note that NetworkManager should be configured to read secrets from a secret agent.
          This can be done for example through the `networking.networkmanager.ensureProfiles.profiles` options.
        '';
        default = [ ];
        example = [
          {
            matchId = "My WireGuard VPN";
            matchType = "wireguard";
            matchSetting = "wireguard";
            key = "private-key";
            file = "/root/wireguard_key";
          }
        ];
        type = lib.types.listOf (
          lib.types.submodule {
            options = {
              matchId = lib.mkOption {
                description = ''
                  connection id used by NetworkManager. Often displayed as name in GUIs.

                  NetworkManager describes this as a human readable unique identifier for the connection, like "Work Wi-Fi" or "T-Mobile 3G".
                '';
                type = lib.types.nullOr lib.types.str;
                default = null;
                example = "wifi1";
              };
              matchUuid = lib.mkOption {
                description = ''
                  UUID of the connection profile

                  UUIDs are assigned once on connection creation and should never change as long as the connection still applies to the same network.
                '';
                type = lib.types.nullOr lib.types.str;
                default = null;
                example = "669ea4c9-4cb3-4901-ab52-f9606590976e";
              };
              matchType = lib.mkOption {
                description = ''
                  NetworkManager connection type

                  The NetworkManager configuration settings reference roughly corresponds to connection types.
                  More might be available on your system depending on the installed plugins.

                  <https://networkmanager.dev/docs/api/latest/ch01.html>
                '';
                type = lib.types.nullOr lib.types.str;
                default = null;
                example = "wireguard";
              };
              matchIface = lib.mkOption {
                description = "interface name of the NetworkManager connection";
                type = lib.types.nullOr lib.types.str;
                default = null;
              };
              matchSetting = lib.mkOption {
                description = "name of the setting section for which secrets are requested";
                type = lib.types.nullOr lib.types.str;
                default = null;
              };
              key = lib.mkOption {
                description = "key in the setting section for which this entry provides a value";
                type = lib.types.str;
              };
              file = lib.mkOption {
                description = "file from which the secret value is read";
                type = lib.types.str;
              };
            };
          }
        );
      };
    };
  };

  ####### implementation
  config = lib.mkIf enabled {
    # start nm-file-secret-agent if required
    systemd.services."nm-file-secret-agent" = {
      description = "NetworkManager secret agent that responds with the content of preconfigured files";
      documentation = [ "https://github.com/lilioid/nm-file-secret-agent/" ];
      requires = [ "NetworkManager.service" ];
      after = [ "NetworkManager.service" ];
      wantedBy = [ "multi-user.target" ];
      restartTriggers = [ nmFileSecretAgentConfigFile ];
      serviceConfig.ExecStart = "${lib.getExe cfg.ensureProfiles.secrets.package} --conf ${nmFileSecretAgentConfigFile}";
    };
  };
}
