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

let
  cfg = config.local.yubikey;

  control = if cfg.multi-factor.enable then "required" else "sufficient";
in
{
  options.local.yubikey = with lib; {
    enable = mkEnableOption "yubikey";

    serial = mkOption {
      type = types.nullOr types.str;
      default = null;
    };

    multi-factor.enable = mkEnableOption "multi-factor" // { default = true; };

    unplug = {
      enable = mkEnableOption "Do action when a Yubikey is unplugged";
      model = mkOption {
        type = types.str;
        default = "407";
      };
      command = mkOption {
        type = types.str;
        default = "${pkgs.systemd}/bin/loginctl lock-sessions";
      };
    };
  };

  config = lib.mkIf cfg.enable {
    environment.systemPackages = [ pkgs.yubikey-manager pkgs.yubikey-personalization ];

    security.pam =
      if cfg.serial == null then
        {
          u2f = {
            enable = true;
            inherit control;
            cue = lib.mkDefault true;
          };

          services = {
            login.u2fAuth = lib.mkDefault true;
            sudo.u2fAuth = lib.mkDefault true;
          };
        }
      else
        {
          yubico = {
            enable = true;
            inherit control;
            mode = "challenge-response";
            id = [ cfg.serial ];
          };
        };

    services.pcscd.enable = cfg.serial != null;

    services.udev = {
      packages = [ pkgs.yubikey-personalization ];
      extraRules = lib.mkIf cfg.unplug.enable ''
        ACTION=="remove",\
         ENV{DEVTYPE}=="usb_device",\
         ENV{PRODUCT}=="1050/${cfg.unplug.model}/543",\
         RUN+="${cfg.unplug.command}"
      '';
    };
  };
}