import ../make-test-python.nix ({ lib, pkgs, ... }: let
  oldNetbox = pkgs.netbox_3_7;
  newNetbox = pkgs.netbox_4_1;
in {
  name = "netbox-upgrade";

  meta = with lib.maintainers; {
    maintainers = [ minijackson raitobezarius ];
  };

  nodes.machine = { config, ... }: {
    virtualisation.memorySize = 2048;
    services.netbox = {
      enable = true;
      package = oldNetbox;
      secretKeyFile = pkgs.writeText "secret" ''
        abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
      '';
    };

    services.nginx = {
      enable = true;

      recommendedProxySettings = true;

      virtualHosts.netbox = {
        default = true;
        locations."/".proxyPass = "http://localhost:${toString config.services.netbox.port}";
        locations."/static/".alias = "/var/lib/netbox/static/";
      };
    };

    users.users.nginx.extraGroups = [ "netbox" ];

    networking.firewall.allowedTCPPorts = [ 80 ];

    specialisation.upgrade.configuration.services.netbox.package = lib.mkForce newNetbox;
  };

  testScript = { nodes, ... }:
    let
      apiVersion = version: lib.pipe version [
        (lib.splitString ".")
        (lib.take 2)
        (lib.concatStringsSep ".")
      ];
      oldApiVersion = apiVersion oldNetbox.version;
      newApiVersion = apiVersion newNetbox.version;
    in
    ''
      start_all()
      machine.wait_for_unit("netbox.target")
      machine.wait_for_unit("nginx.service")
      machine.wait_until_succeeds("journalctl --since -1m --unit netbox --grep Listening")

      def api_version(headers):
          header = [header for header in headers.splitlines() if header.startswith("API-Version:")][0]
          return header.split()[1]

      def check_api_version(version):
          # Returns 403 with NetBox >= 4.0,
          # but we still get the API version in the headers
          headers = machine.succeed(
            "curl -sSL http://localhost/api/ --head -H 'Content-Type: application/json'"
          )
          assert api_version(headers) == version

      with subtest("NetBox version is the old one"):
          check_api_version("${oldApiVersion}")

      # Somehow, even though netbox-housekeeping.service has After=netbox.service,
      # netbox-housekeeping.service and netbox.service still get started at the
      # same time, making netbox-housekeeping fail (can't really do some house
      # keeping job if the database is not correctly formed).
      #
      # So we don't check that the upgrade went well, we just check that
      # netbox.service is active, and that netbox-housekeeping can be run
      # successfully afterwards.
      #
      # This is not good UX, but the system should be working nonetheless.
      machine.execute("${nodes.machine.system.build.toplevel}/specialisation/upgrade/bin/switch-to-configuration test >&2")

      machine.wait_for_unit("netbox.service")
      machine.succeed("systemctl start netbox-housekeeping.service")

      with subtest("NetBox version is the new one"):
          check_api_version("${newApiVersion}")
    '';
})