{
  config,
  utils,
  pkgs,
  lib,
  ...
}: let
  inherit (lib) mkIf mkMerge mkDefault mkOptionDefault mkOption mkEnableOption types
    getExe;
  nixosConfig = config;
  cfg = config.services.vouch-proxy;
  settingsFormat = pkgs.formats.json { };
in {
  options.services.vouch-proxy = with types; {
    enable = mkEnableOption "vouch";
    user = mkOption {
      type = str;
      default = "vouch-proxy";
    };
    group = mkOption {
      type = str;
      default = "vouch-proxy";
    };
    authUrl = mkOption {
      type = str;
      default = config.services.kanidm.serverSettings.origin;
    };
    domain = mkOption {
      type = str;
      default = config.networking.domain;
    };
    url = mkOption {
      type = str;
      default = "https://${cfg.domain}";
    };
    enableSettingsSecrets = mkEnableOption "genJqSecretsReplacementSnippet";
    settings = let
      settingsModule = { ... }: {
        freeformType = settingsFormat.type;
        options = {
          vouch = {
            cookie = {
              domain = mkOption {
                type = nullOr str;
                default = nixosConfig.networking.domain;
              };
              secure = mkOption {
                type = bool;
                default = true;
              };
            };
            port = mkOption {
              type = port;
              default = 30746;
            };
            listen = mkOption {
              type = nullOr str;
              default = "127.0.0.1";
            };
            allowAllUsers = mkOption {
              type = bool;
              default = true;
            };
          };
          oauth = {
            auth_url = mkOption {
              type = str;
              default = "${cfg.authUrl}/ui/oauth2";
            };
            token_url = mkOption {
              type = str;
              default = "${cfg.authUrl}/oauth2/token";
            };
            user_info_url = mkOption {
              type = str;
              default = "${cfg.authUrl}/oauth2/openid/vouch/userinfo";
            };
            scopes = mkOption {
              type = listOf str;
              default = ["openid" "email" "profile"];
            };
            callback_url = mkOption {
              type = str;
              default = "${cfg.url}/auth";
            };
            provider = mkOption {
              type = nullOr str;
              default = "oidc";
            };
            code_challenge_method = mkOption {
              type = str;
              default = "S256";
            };
            client_id = mkOption {
              type = str;
              default = "vouch";
            };
          };
        };
      };
    in mkOption {
      type = submodule settingsModule;
      default = { };
    };
    extraSettings = mkOption {
      inherit (settingsFormat) type;
      default = { };
    };
    settingsPath = mkOption {
      type = path;
    };
  };
  config = let
    recursiveMergeAttrs = listOfAttrsets: lib.fold (attrset: acc: lib.recursiveUpdate attrset acc) {} listOfAttrsets;
    settings = recursiveMergeAttrs [
      cfg.settings
      cfg.extraSettings
    ];
    settingsPath = if cfg.enableSettingsSecrets
      then "/run/vouch-proxy/vouch-config.json"
      else settingsFormat.generate "vouch-config.json" settings;
  in mkMerge [
    {
      services.vouch-proxy = {
        settingsPath = mkOptionDefault settingsPath;
      };
    }
    (mkIf cfg.enable {
      systemd.services.vouch-proxy = {
        description = "Vouch-proxy";
        after = [ "network.target" ];
        wantedBy = [ "multi-user.target" ];
        serviceConfig = {
          ExecStartPre = let
            preprocess = pkgs.writeShellScript "vouch-proxy-prestart" (
              utils.genJqSecretsReplacementSnippet settings cfg.settingsPath
            );
          in mkIf cfg.enableSettingsSecrets [
            "${preprocess}"
          ];
          ExecStart = [
            "${getExe pkgs.vouch-proxy} -config ${cfg.settingsPath}"
          ];
          Restart = "on-failure";
          RestartSec = mkDefault 5;
          WorkingDirectory = "/var/lib/vouch-proxy";
          StateDirectory = "vouch-proxy";
          RuntimeDirectory = "vouch-proxy";
          User = cfg.user;
          Group = cfg.group;
          StartLimitBurst = mkDefault 3;
        };
      };

      users.users.${cfg.user} = {
        inherit (cfg) group;
        isSystemUser = true;
      };

      users.groups.${cfg.group} = {};
    })
  ];
}
