# SPDX-FileCopyrightText: 2025 Ryan Lahfa <ryan.lahfa@dgnum.eu>
#
# SPDX-License-Identifier: MIT

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

let
  inherit (lib)
    getExe
    getExe'
    hasAttrByPath
    mkEnableOption
    mkIf
    mkOption
    mkPackageOption
    optional
    ;

  inherit (lib.types) listOf str submodule;

  inherit (utils) escapeSystemdExecArgs genJqSecretsReplacementSnippet;

  settingsFormat = pkgs.formats.json { };

  cfg = config.services.openbao;
in
{
  options = {
    services.openbao = {
      enable = mkEnableOption "OpenBao daemon";

      package = mkPackageOption pkgs "openbao" { };

      settings = mkOption {
        description = ''
          Settings of OpenBao.

          See [documentation](https://openbao.org/docs/configuration/) for more details.
        '';
        type = submodule {
          freeformType = settingsFormat.type;
          options = {
            listener.tcp.address = mkOption {
              type = str;
              default = "127.0.0.1:8200";
              description = ''
                The address the OpenBao daemon will listen to.
              '';
            };
          };
        };
      };

      extraArgs = mkOption {
        type = listOf str;
        default = [ ];
        description = ''
          Additional arguments given to OpenBao
        '';
      };
    };
  };

  config = mkIf cfg.enable {
    environment.systemPackages = [ pkgs.openbao ];

    systemd.services.openbao = {
      description = "OpenBao server daemon";

      wantedBy = [ "multi-user.target" ];
      after =
        [ "network.target" ]
        ++ optional (
          config.services.consul.enable && (hasAttrByPath [ "storage" "consul" ] cfg.settings)
        ) "consul.service";

      restartIfChanged = false; # do not restart on "nixos-rebuild switch". It would seal the storage and disrupt the clients.
      preStart = genJqSecretsReplacementSnippet cfg.settings "/var/lib/openbao/config.json";

      startLimitIntervalSec = 60;
      startLimitBurst = 3;
      serviceConfig = {
        DynamicUser = true;
        ExecStart = escapeSystemdExecArgs (
          [
            (getExe cfg.package)
            "server"
            "-config"
            "/var/lib/openbao/config.json"
          ]
          ++ cfg.extraArgs
        );
        ExecReload = "${getExe' pkgs.coreutils "kill"} -SIGHUP $MAINPID";
        StateDirectory = "openbao";
        UMask = "0077";
        AmbientCapabilities = "cap_ipc_lock";
        KillSignal = "SIGINT";
        LimitCORE = 0;
        NoNewPrivileges = true;
        PrivateDevices = true;
        PrivateTmp = true;
        ProtectHome = "read-only";
        ProtectSystem = "full";
        Restart = "on-failure";
        TimeoutStopSec = "30s";
      };
    };
  };

}