{
  config,
  lib,
  pkgs,
  ...
}:
with lib; let
  serviceName = "vaultwarden";
  cfg = config.homelab.services.${serviceName};
  homelabCfg = config.homelab;
in {
  imports = [
    (import ../lib/features/monitoring.nix serviceName)
    (import ../lib/features/logging.nix serviceName)
    (import ../lib/features/proxy.nix serviceName)
  ];

  # Core service options
  options.homelab.services.${serviceName} = {
    enable = mkEnableOption "Vault Warden";

    description = mkOption {
      type = types.str;
      default = "Vault Warden";
    };

    port = mkOption {
      type = types.port;
      default = 8222;
    };

    openFirewall = mkOption {
      type = types.bool;
      default = true;
      description = ''
        Whether to open the ports specified in `port` and `webPort` in the firewall.
      '';
    };

    environmentFile = lib.mkOption {
      type = with lib.types; nullOr path;
      default = null;
      example = "/var/lib/vaultwarden.env";
      description = ''
        Additional environment file as defined in {manpage}`systemd.exec(5)`.

        Secrets like {env}`ADMIN_TOKEN` and {env}`SMTP_PASSWORD`
        should be passed to the service without adding them to the world-readable Nix store.

        Note that this file needs to be available on the host on which `vaultwarden` is running.

        As a concrete example, to make the Admin UI available (from which new users can be invited initially),
        the secret {env}`ADMIN_TOKEN` needs to be defined as described
        [here](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page):

        ```
        # Admin secret token, see
        # https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page
        ADMIN_TOKEN=...copy-paste a unique generated secret token here...
        ```
      '';
    };

    systemdServices = mkOption {
      type = types.listOf types.str;
      default = [
        "vaultwarden.service"
        "vaultwarden"
      ];
      description = "Systemd services to monitor";
    };
  };

  # Service configuration with smart defaults
  config = mkIf cfg.enable (mkMerge [
    {
      services.vaultwarden = {
        enable = true;
        config = {
          DOMAIN = "https://bitwarden.example.com";
          SIGNUPS_ALLOWED = false;

          ROCKET_ADDRESS = "0.0.0.0";
          ROCKET_PORT = cfg.port;

          ROCKET_LOG = "critical";

          # This example assumes a mailserver running on localhost,
          # thus without transport encryption.
          # If you use an external mail server, follow:
          #   https://github.com/dani-garcia/vaultwarden/wiki/SMTP-configuration
          # SMTP_HOST = "127.0.0.1";
          # SMTP_PORT = 25;
          # SMTP_SSL = false;

          # SMTP_FROM = "admin@bitwarden.example.com";
          # SMTP_FROM_NAME = "example.com Bitwarden server";

          ADMIN_TOKEN = "1234";
        };
        environmentFile = cfg.environmentFile;
      };

      networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [cfg.port];
    }
    {
      # homelab.services.${serviceName}.monitoring = {
      #   metrics.path = "/metrics";

      #   healthCheck.path = "/healthz";
      #   healthCheck.conditions = ["[STATUS] == 200" "[RESPONSE_TIME] < 1000"];

      #   extraLabels = {
      #     component = "example";
      #   };
      # };
    }
    {
      # homelab.services.${serviceName}.logging = {
      #   files = ["/var/log/example/log.log"];
      #   # parsing = {
      #   #   regex = "^ts=(?P<timestamp>[^ ]+) caller=(?P<caller>[^ ]+) level=(?P<level>\\w+) msg=\"(?P<message>[^\"]*)\"";
      #   #   extractFields = ["level" "caller"];
      #   # };
      #   extraLabels = {
      #     component = "example";
      #     application = "example";
      #   };
      # };
    }
    {
      homelab.services.${serviceName}.proxy = {
        enableAuth = true;
      };
    }
  ]);
}
