{ config, lib, pkgs, ... }:
with lib;
let
  cfg = config.mossnet.wg;
in
{
  options = {
    mossnet.wg = {
      enable = mkEnableOption "Gain access to all mossnet systems through wireguard";
      ips = lib.mkOption {
        type = with types; listOf str;
        default = { };
        example = literalExample ''
          [ "10.0.69.2/24" ];
        '';
        description = ''
          The IP this machine is allowed to connect to
        '';
      };
      privateKeyFile = lib.mkOption {
        type = types.path;
        default = { };
        example = literalExample ''
          /run/agenix/wg-curve
        '';
        description = ''
          The private ssh key file to use to connect!
          Remember set age.secrets.*.file and age.secrets.*.user
        '';
      };
    };
  };
  config = mkIf cfg.enable {
    networking.firewall.allowedUDPPorts = [ 60990 ];
    networking.wireguard.interfaces = {
      wg0 = {
        ips = cfg.ips;
        listenPort = 60990; # to match firewall allowedUDPPorts (without this wg uses random port numbers)

        privateKeyFile = cfg.privateKeyFile;
        peers = [
          # For a client configuration, one peer entry for the server will suffice.
          {
            publicKey = "c1J4p63rD3IlszugMZiki7UBV3YmDdqa3DU4UejXzAI=";
            allowedIPs = [ "10.0.69.0/24" ];
            # Set this to the server IP and port.
            endpoint = "sealight.xyz:60990"; # ToDo: route to endpoint not automatically configured https://wiki.archlinux.org/index.php/WireGuard#Loop_routing https://discourse.nixos.org/t/solved-minimal-firewall-setup-for-wireguard-client/7577
            persistentKeepalive = 25;
          }
        ];
      };
    };

    # Ensure WireGuard restarts on failure
    systemd.services.wireguard-wg0 = {
      serviceConfig = {
        Restart = "on-failure";
        RestartSec = "5s";
      };
    };

    # Periodic connection health check and reconnect
    systemd.services.wireguard-wg0-healthcheck = {
      description = "WireGuard wg0 connection health check";
      after = [ "network-online.target" "wireguard-wg0.service" ];
      wants = [ "network-online.target" ];
      serviceConfig = {
        Type = "oneshot";
        ExecStart = pkgs.writeShellScript "wg0-healthcheck" ''
          # Check if we can ping the WireGuard gateway
          if ! ${pkgs.iputils}/bin/ping -c 1 -W 5 10.0.69.1 &>/dev/null; then
            echo "WireGuard connection down, restarting..."
            ${pkgs.systemd}/bin/systemctl restart wireguard-wg0.service
          fi
        '';
      };
    };

    systemd.timers.wireguard-wg0-healthcheck = {
      description = "Timer for WireGuard wg0 health check";
      wantedBy = [ "timers.target" ];
      timerConfig = {
        OnBootSec = "2min";
        OnUnitActiveSec = "2min";
        Unit = "wireguard-wg0-healthcheck.service";
      };
    };
  };
}
