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

let
  hasForgejoApiToken = builtins.pathExists ../../secrets/forgejo-api-token.age;
  hasNetbootChainToken = builtins.pathExists ../../secrets/netboot-chain-token.age;
  hasOpStackSepoliaKey = builtins.pathExists ../../secrets/op-stack-sepolia-private-key.age;
  hasOpStackChallengerPrestate = builtins.pathExists ../../secrets/op-stack-challenger-prestate.bin.gz.age;
in
{
  imports = [
    ./ecp-forge-hardware.nix
  ];

  nixpkgs.config.allowUnfreePredicate = pkg:
    builtins.elem (lib.getName pkg) [
      "google-chrome"
      "google-chrome-stable"
    ];

  networking = {
    hostName = "ecp-forge";
    hostId = "007f0200";
    useDHCP = lib.mkForce true;
    networkmanager.enable = lib.mkForce false;
    nameservers = [ "1.1.1.1" "8.8.8.8" ];
    firewall = {
      trustedInterfaces = [ "tailscale0" ];
      allowedTCPPorts = [
        80
        443
        2222
        69
      ];
      allowedUDPPorts = [
        67
        69
      ];
    };
  };

  services.openssh = {
    enable = true;
    startWhenNeeded = true;
    openFirewall = true;
    settings = {
      PasswordAuthentication = false;
      PermitRootLogin = lib.mkForce "prohibit-password";
      KbdInteractiveAuthentication = false;
    };
  };

  users.users.root.openssh.authorizedKeys.keys = [
    "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBueQxNbP2246pxr/m7au4zNVm+ShC96xuOcfEcpIjWZ"
  ];

  security.sudo = {
    execWheelOnly = true;
    wheelNeedsPassword = false;
  };

  users = {
    mutableUsers = false;
    defaultUserShell = pkgs.bash;
    users.conradev = {
      uid = 1000;
      isNormalUser = true;
      password = "password";
      group = "conradev";
      extraGroups = [ "wheel" "docker" "libvirtd" "kvm" ];
      openssh.authorizedKeys.keys = [
        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBueQxNbP2246pxr/m7au4zNVm+ShC96xuOcfEcpIjWZ"
      ];
    };
    groups.conradev = { };
    groups.forgejo-runner = {
      gid = 984;
    };
    users.forgejo-runner = {
      uid = 989;
      isSystemUser = true;
      group = "forgejo-runner";
      home = "/var/lib/forgejo-runner-agent";
      createHome = true;
    };
  };

  boot.loader = {
    grub = {
      enable = true;
      device = "/dev/disk/by-id/nvme-KIOXIA_KCD81RUG7T68_25R0A0KZTTEJ";
    };
    efi.canTouchEfiVariables = false;
  };

  boot.supportedFilesystems = [ "zfs" ];
  boot.zfs.extraPools = [ "tank" ];
  boot.kernel.sysctl = {
    "fs.inotify.max_user_watches" = "204800";
  };

  hardware.nvidia-container-toolkit.enable = false;

  virtualisation = {
    containers.enable = true;
    oci-containers.backend = "podman";
    podman = {
      enable = true;
      dockerCompat = true;
      autoPrune.enable = true;
      defaultNetwork.settings.dns_enabled = true;
    };
  };

  services.tailscale = {
    enable = true;
    extraUpFlags = "--accept-routes";
  };

  age.identityPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
  age.secrets = lib.mkMerge [
    (lib.mkIf hasForgejoApiToken {
      "forgejo-api-token" = {
        file = ../../secrets/forgejo-api-token.age;
        owner = "root";
        group = "root";
        mode = "0400";
      };
    })
    (lib.mkIf hasNetbootChainToken {
      "every-channel-netboot-chain-token" = {
        file = ../../secrets/netboot-chain-token.age;
        owner = "root";
        group = "root";
        mode = "0400";
      };
    })
    (lib.mkIf hasOpStackSepoliaKey {
      "every-channel-op-stack-sepolia-private-key" = {
        file = ../../secrets/op-stack-sepolia-private-key.age;
        owner = "root";
        group = "root";
        mode = "0400";
      };
    })
    (lib.mkIf hasOpStackChallengerPrestate {
      "every-channel-op-stack-challenger-prestate" = {
        file = ../../secrets/op-stack-challenger-prestate.bin.gz.age;
        owner = "root";
        group = "root";
        mode = "0400";
      };
    })
  ];

  services.zfs.autoScrub = {
    enable = true;
    pools = [ "tank" ];
    interval = "weekly";
  };

  services.nfs.server = {
    enable = true;
    # Keep NFS on trusted/private paths only; public Hetzner exposure triggers
    # rpcbind/portmapper enumeration and is not needed for forge access.
    exports = ''
      /tank 10.0.0.0/8(rw,fsid=0,crossmnt,no_subtree_check,sync) 100.64.0.0/10(rw,fsid=0,crossmnt,no_subtree_check,sync) 192.168.0.0/16(rw,fsid=0,crossmnt,no_subtree_check,sync)
    '';
  };

  nix.gc = {
    automatic = true;
    dates = "weekly";
    options = "--delete-older-than 30d";
  };

  nix.settings = {
    experimental-features = [ "nix-command" "flakes" ];
    substituters = lib.mkForce [ "https://cache.nixos.org" ];
    trusted-substituters = lib.mkForce [ "https://cache.nixos.org" ];
    extra-substituters = lib.mkForce [ ];
    trusted-public-keys = lib.mkForce [
      "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
    ];
    extra-trusted-public-keys = lib.mkForce [ ];
  };

  time.timeZone = "America/New_York";
  i18n.defaultLocale = "en_US.UTF-8";
  xdg.mime.enable = true;

  services.forgejo = {
    enable = true;
    database.type = "sqlite3";
    lfs.enable = true;
    settings = {
      server = {
        DOMAIN = "git.every.channel";
        ROOT_URL = "https://git.every.channel/";
        HTTP_ADDR = "127.0.0.1";
        HTTP_PORT = 3000;
        SSH_DOMAIN = "git.every.channel";
        SSH_PORT = 2222;
        SSH_LISTEN_PORT = 2222;
        START_SSH_SERVER = true;
      };
      service = {
        DISABLE_REGISTRATION = true;
        REQUIRE_SIGNIN_VIEW = false;
      };
      repository = {
        DEFAULT_BRANCH = "main";
      };
    };
  };

  systemd.tmpfiles.rules = [
    "d /var/lib/forgejo-runner-agent 0750 forgejo-runner forgejo-runner -"
  ];

  systemd.services.forgejo-runner-agent = {
    description = "Forgejo Actions runner for every.channel";
    after = [ "network-online.target" "forgejo.service" ];
    wants = [ "network-online.target" ];
    wantedBy = [ "multi-user.target" ];
    path = with pkgs; [
      bash
      coreutils
      curl
      git
      gnugrep
      gnused
      gnutar
      gzip
      nix
      which
      zstd
    ];
    environment = {
      HOME = "/var/lib/forgejo-runner-agent";
    };
    serviceConfig = {
      User = "forgejo-runner";
      Group = "forgejo-runner";
      WorkingDirectory = "/var/lib/forgejo-runner-agent";
      ExecStart = "${pkgs.forgejo-runner}/bin/forgejo-runner --config /var/lib/forgejo-runner-agent/runner.yaml daemon";
      Restart = "always";
      RestartSec = "10s";
    };
  };

  services.caddy = {
    enable = true;
    email = "infra@every.channel";
    acmeCA = "https://acme-v02.api.letsencrypt.org/directory";
    virtualHosts = {
      "git.every.channel".extraConfig = ''
        reverse_proxy http://127.0.0.1:3000
      '';
      "forge.every.channel".extraConfig = ''
        redir https://git.every.channel{uri} permanent
      '';
    };
  };

  services.every-channel.netboot = {
    enable = true;
    listenIP = "95.216.114.54";
    interface = "enp5s0f3u2u2c2";
    hostname = "boot.every.channel";
    httpPort = 8080;
    tftpBootFilename = "ec-ipxe.efi";
    httpAllowedCIDRs = [
      "10.0.0.0/8"
      "172.16.0.0/12"
      "192.168.0.0/16"
      "100.64.0.0/10"
    ];
    chainTokenFile =
      if hasNetbootChainToken
      then config.age.secrets."every-channel-netboot-chain-token".path
      else null;
    proxyDhcp.enable = false;
    release.host = "https://git.every.channel";
    release.repo = "every-channel/every.channel";
    release.localTarball = "/var/lib/every-channel-netboot/sources/ec-runner-x86_64-netboot-local.tar.gz";
    release.tokenFile =
      if hasForgejoApiToken
      then config.age.secrets."forgejo-api-token".path
      else null;
  };

  services.every-channel.ipxe-qemu = {
    enable = true;
    name = "ecp-forge-ipxe";
    boot.userNet.hostname = "ecp-forge-ipxe";
    boot.http.root = "${config.services.every-channel.netboot.rootDir}/http";
  };

  systemd.services.every-channel-ipxe-qemu = {
    after = [ "every-channel-netboot-stage.service" ];
    wants = [ "every-channel-netboot-stage.service" ];
  };

  services.every-channel.ec-node = {
    enable = true;
    nbc = {
      enable = true;
      chromeBinary = "${pkgs.google-chrome}/bin/google-chrome-stable";
      display = ":120";
      screen = "1920x1080x24";
      isolateWithUserNetns = true;
      requireMullvad = false;
      mullvadLocation = null;
      mvpdUsernameFile = "/var/lib/every-channel/nbc-auth/verizon-user.txt";
      mvpdPasswordFile = "/var/lib/every-channel/nbc-auth/verizon-pass.txt";
      noSandbox = true;
      vnc = {
        enable = true;
        listen = "127.0.0.1";
        port = 5900;
      };
    };
    broadcasts = [
      {
        name = "forge-nbc-sports-philly";
        nbcUrl = "https://www.nbc.com/live?brand=nbc-sports-philadelphia";
      }
    ];
    archive = {
      enable = true;
      outputDir = "/tank/every-channel/archive";
      manifestDir = "/var/lib/every-channel/manifests";
      # Keep forge archival as an ingest worker only; replay serving is separate.
      serve.enable = false;
    };
  };

  services.every-channel.ethereum = {
    enable = true;
    poolName = "eth";
    poolDevice = "/dev/disk/by-id/nvme-eui.01000000000000008ce38ee307de5c01";
    rootDir = "/eth";
    publicIp = "95.216.114.54";
    publicHost = "eth.every.channel";
  };

  services.mullvad-vpn = {
    enable = false;
    enableExcludeWrapper = false;
  };

  services.every-channel.op-stack = {
    enable = hasOpStackSepoliaKey;
    challengerEnable = hasOpStackChallengerPrestate;
    disputeMonEnable = hasOpStackChallengerPrestate;
    privateKeyFile =
      if hasOpStackSepoliaKey
      then config.age.secrets."every-channel-op-stack-sepolia-private-key".path
      else null;
    challengerPrestateFile =
      if hasOpStackChallengerPrestate
      then config.age.secrets."every-channel-op-stack-challenger-prestate".path
      else null;
    p2pAdvertiseIp = "95.216.114.54";
  };

  environment.systemPackages =
    (with pkgs; [
      git
      google-chrome
      htop
      jq
      mullvad-vpn
      tmux
      x11vnc
      zfs
    ])
    ++ [
      config.services.every-channel.ec-node.package
    ];

  system.stateVersion = "22.11";
}
