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

with lib;

let
  cfg = config.services.openssh;

  Ciphers = [
    "chacha20-poly1305@openssh.com"
    "aes256-gcm@openssh.com"
    "aes256-ctr"
  ];
  Macs = [
    "umac-128-etm@openssh.com"
    "hmac-sha2-256-etm@openssh.com"
    "hmac-sha2-512-etm@openssh.com"
    "umac-128@openssh.com"
    "hmac-sha2-256"
    "hmac-sha2-512"
    "umac-64-etm@openssh.com"
    "umac-64@openssh.com"
  ];
  KexAlgorithms = [
    "sntrup761x25519-sha512@openssh.com"
    "curve25519-sha256"
    "curve25519-sha256@libssh.org"
    "diffie-hellman-group-exchange-sha256"
  ];
  HostKeyAlgorithms = [
    "sk-ssh-ed25519-cert-v01@openssh.com"
    "ssh-ed25519-cert-v01@openssh.com"
    "rsa-sha2-256-cert-v01@openssh.com"
    "rsa-sha2-512-cert-v01@openssh.com"
    "sk-ssh-ed25519@openssh.com"
    "ssh-ed25519"
    "rsa-sha2-256"
    "rsa-sha2-512"
  ];
  CASignatureAlgorithms = [
    "sk-ssh-ed25519@openssh.com"
    "ssh-ed25519"
    "rsa-sha2-256"
    "rsa-sha2-512"
  ];
  PubkeyAcceptedAlgorithms = [
    "ssh-ed25519-cert-v01@openssh.com"
    "sk-ssh-ed25519-cert-v01@openssh.com"
    "rsa-sha2-512-cert-v01@openssh.com"
    "rsa-sha2-256-cert-v01@openssh.com"
    "ssh-ed25519"
    "ssh-rsa"
  ];
in {
  options = {
    services.openssh = {
      staticHostKeys = mkOption {
        type = types.bool;
        default = pathExists (./host-keys + "/${hostName}.yaml");
      };
    };
  };

  config = {
    systemd.user.services."ssh-agent".enable = mkForce false; # ssh-agent should be done via home-manager

    services.openssh = mkIf cfg.enable {
      startWhenNeeded = true;
      hostKeys = mkIf cfg.staticHostKeys (mkForce []); # done manually
      settings = {
        inherit Ciphers Macs KexAlgorithms;
        HostKeyAlgorithms = concatStringsSep "," HostKeyAlgorithms;
        PubkeyAcceptedAlgorithms = concatStringsSep "," PubkeyAcceptedAlgorithms;
        CASignatureAlgorithms = concatStringsSep "," CASignatureAlgorithms;

        LogLevel = "VERBOSE";
        RevokedKeys = toString ./ca/krl.bin;

        PasswordAuthentication = mkDefault false;
        KbdInteractiveAuthentication = mkDefault false;
      };
      extraConfig = optionalString cfg.staticHostKeys ''
        HostCertificate ${./known-hosts + "/${hostName}/ed25519-cert.pub"}
        HostCertificate ${./known-hosts + "/${hostName}/rsa-cert.pub"}
      '';
    };

    systemd.services = mkIf cfg.enable {
      "sshd@" = {
        restartIfChanged = false;
        serviceConfig = {
          ExecStart = mkForce (concatStringsSep " " (
            [ "-${cfg.package or pkgs.openssh}/bin/sshd" "-i" "-D" "-f" "/etc/ssh/sshd_config" ]
            ++ optional (config.sops.secrets ? "ssh_moduli") ''-o "moduliFile ''${CREDENTIALS_DIRECTORY}/ssh_moduli"''
            ++ optional cfg.staticHostKeys ''-o "HostKey ''${CREDENTIALS_DIRECTORY}/ssh_host_ed25519_key" -o "HostKey ''${CREDENTIALS_DIRECTORY}/ssh_host_rsa_key"''
          ));
          LoadCredential =
            lib.optional (config.sops.secrets ? "ssh_moduli") "ssh_moduli:${config.sops.secrets.ssh_moduli.path}"
            ++ lib.optionals cfg.staticHostKeys [
              "ssh_host_ed25519_key:${config.sops.secrets.ssh_host_ed25519_key.path}"
              "ssh_host_rsa_key:${config.sops.secrets.ssh_host_rsa_key.path}"
            ];
        };
      };
    };
    systemd.sockets."sshd@run-ssh\\x2dunix\\x2dlocal-socket" = mkIf cfg.enable {
      wantedBy = ["sockets.target"];
      listenStreams = ["/run/ssh-unix-local/socket"];
      socketConfig = {
        Accept = true;
        PollLimitIntervalSec = "30s";
        PollLimitBurst = 50;
      };
    };

    programs.ssh = {
      knownHosts = {
        "*.yggdrasil.li" = {
          extraHostNames = ["*.yggdrasil"];
          certAuthority = true;
          publicKeyFile = ./ca/ca.pub;
        };
      };
      knownHostsFiles = [
        ./known-hosts/borgbase.keys
      ];

      ciphers = Ciphers;
      macs = Macs;
      kexAlgorithms = KexAlgorithms;
      hostKeyAlgorithms = HostKeyAlgorithms;
      pubkeyAcceptedKeyTypes = PubkeyAcceptedAlgorithms;

      extraConfig = ''
        Host *
          CASignatureAlgorithms ${concatStringsSep "," CASignatureAlgorithms}
          PasswordAuthentication no
          KbdInteractiveAuthentication no

        Host unix/* vsock/* vsock-mux/*
            ProxyCommand ${config.systemd.package}/lib/systemd/systemd-ssh-proxy %h %p
            ProxyUseFdpass yes
            CheckHostIP no

        Host .host ${config.networking.hostName} ${config.networking.hostName}.yggdrasil localhost ::1 127.0.0.0/8
            HostKeyAlias ${config.networking.hostName}.yggdrasil
            ProxyCommand ${config.systemd.package}/lib/systemd/systemd-ssh-proxy unix/run/ssh-unix-local/socket %p
            ProxyUseFdpass yes
            CheckHostIP no
      '';
    };

    sops.secrets = mkIf cfg.enable {
      ssh_host_rsa_key = mkIf cfg.staticHostKeys {
        key = "rsa";
        sopsFile = ./host-keys + "/${hostName}.yaml";
      };
      ssh_host_ed25519_key = mkIf cfg.staticHostKeys {
        key = "ed25519";
        sopsFile = ./host-keys + "/${hostName}.yaml";
      };
      ssh_moduli = mkIf (pathExists (./host-moduli + "/${hostName}")) {
        format = "binary";
        sopsFile = ./host-moduli + "/${hostName}";
      };
    };

    environment.systemPackages = mkIf cfg.enable (with pkgs; [
      kitty.terminfo
    ]);
  };
}