{ pkgs, self }:
let
  lib = pkgs.lib;

  ## FIXME: this binding was not used but maybe we want a side effect or something?
  # rebuildableTest = import ./rebuildableTest.nix pkgs;

  email = "test@test.com";
  password = "testtest";

  # FIXME: Replace all the By.XPATH by By.CSS_SELECTOR.

  seleniumImports = ''
    import sys
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.chrome.options import Options
  '';

  seleniumSetup = ''
    print("Create and configure driver...", file=sys.stderr)
    options = Options()
    # options.add_argument("--headless=new")
    service = webdriver.ChromeService(executable_path="${lib.getExe pkgs.chromedriver}")  # noqa: E501
    driver = webdriver.Chrome(options=options, service=service)
    driver.implicitly_wait(30)
    driver.set_window_size(1280, 960)
  '';

  seleniumPixelfedLogin = ''
    print("Open login page...", file=sys.stderr)
    driver.get("http://pixelfed.localhost/login")
    print("Enter email...", file=sys.stderr)
    driver.find_element(By.ID, "email").send_keys("${email}")
    print("Enter password...", file=sys.stderr)
    driver.find_element(By.ID, "password").send_keys("${password}")
    # FIXME: This is disgusting. Find instead the input type submit in the form
    # with action ending in "/login".
    print("Click “Login” button...", file=sys.stderr)
    driver.find_element(By.XPATH, "//button[normalize-space()='Login']").click()
  '';

  ## NOTE: `path` must be a valid python string, either a variable or _quoted_.
  seleniumTakeScreenshot = path: ''
    print("Take screenshot...", file=sys.stderr)
    if not driver.save_screenshot(${path}):
        raise Exception("selenium could not save screenshot")
  '';

  seleniumQuit = ''
    print("Quitting...", file=sys.stderr)
    driver.quit()
  '';

  seleniumScriptPostPicture =
    pkgs.writers.writePython3Bin "selenium-script-post-picture"
      { libraries = with pkgs.python3Packages; [ selenium ]; }
      ''
        import os
        import time
        ${seleniumImports}
        from selenium.webdriver.support.wait import WebDriverWait

        ${seleniumSetup}
        ${seleniumPixelfedLogin}
        time.sleep(3)

        media_path = os.environ['POST_MEDIA']

        # Find the new post form, fill it in with our pictureand a caption.
        print("Click on “Create New Post”...", file=sys.stderr)
        driver.find_element(By.LINK_TEXT, "Create New Post").click()
        print("Add file to input element...", file=sys.stderr)
        driver.find_element(By.XPATH, "//input[@type='file']").send_keys(media_path)
        print("Add a caption", file=sys.stderr)
        driver.find_element(By.CSS_SELECTOR, ".media-body textarea").send_keys(
            "Fediversity test of image upload to pixelfed with garage storage."
        )
        time.sleep(3)
        print("Click on “Post” button...", file=sys.stderr)
        driver.find_element(By.LINK_TEXT, "Post").click()

        # Wait until the post loads, and in particular its picture, then take a
        # screenshot of the whole page.
        print("Wait for post and image to be loaded...", file=sys.stderr)
        img = driver.find_element(
            By.XPATH,
            "//div[@class='timeline-status-component-content']//img"
        )
        WebDriverWait(driver, timeout=10).until(
            lambda d: d.execute_script("return arguments[0].complete", img)
        )
        time.sleep(3)

        ${seleniumTakeScreenshot "\"/home/selenium/screenshot.png\""}
        ${seleniumQuit}'';

  seleniumScriptGetSrc =
    pkgs.writers.writePython3Bin "selenium-script-get-src"
      { libraries = with pkgs.python3Packages; [ selenium ]; }
      ''
        ${seleniumImports}
        ${seleniumSetup}
        ${seleniumPixelfedLogin}

        img = driver.find_element(
            By.XPATH,
            "//div[@class='timeline-status-component-content']//img"
        )
        # REVIEW: Need to wait for it to be loaded?
        print(img.get_attribute('src'))

        ${seleniumQuit}'';

in
pkgs.nixosTest {
  name = "test-pixelfed-garage";

  nodes = {
    server =
      { config, ... }:
      {

        services = {
          xserver = {
            enable = true;
            displayManager.lightdm.enable = true;
            desktopManager.lxqt.enable = true;
          };

          displayManager.autoLogin = {
            enable = true;
            user = "selenium";
          };
        };
        virtualisation.resolution = {
          x = 1680;
          y = 1050;
        };

        virtualisation = {
          memorySize = lib.mkVMOverride 8192;
          cores = 8;
        };
        imports = with self.nixosModules; [
          fediversity
          ../vm/garage-vm.nix
          ../vm/pixelfed-vm.nix
        ];
        # TODO: pair down
        environment.systemPackages = with pkgs; [
          python3
          chromium
          chromedriver
          xh
          seleniumScriptPostPicture
          seleniumScriptGetSrc
          helix
          imagemagick
        ];
        environment.variables = {
          POST_MEDIA = ./fediversity.png;
          AWS_ACCESS_KEY_ID = config.services.garage.ensureKeys.pixelfed.id;
          AWS_SECRET_ACCESS_KEY = config.services.garage.ensureKeys.pixelfed.secret;
          ## without this we get frivolous errors in the logs
          MC_REGION = "garage";
        };
        # chrome does not like being run as root
        users.users.selenium = {
          isNormalUser = true;
        };
      };
  };

  testScript =
    { nodes, ... }:
    ''
      import re

      server.start()

      with subtest("Pixelfed starts"):
        server.wait_for_unit("phpfpm-pixelfed.service")

      with subtest("Account creation"):
        server.succeed("pixelfed-manage user:create --name=test --username=test --email=${email} --password=${password} --confirm_email=1")

      # NOTE: This could in theory give a false positive if pixelfed changes it's
      # colorscheme to include pure green. (see same problem in mastodon-garage.nix).
      # TODO: For instance: post a red image and check that the green pixel IS NOT
      # there, then post a green image and check that the green pixel IS there.

      with subtest("Image displays"):
        server.succeed("su - selenium -c 'selenium-script-post-picture ${email} ${password}'")
        server.copy_from_vm("/home/selenium/screenshot.png", "")
        displayed_colors = server.succeed("magick /home/selenium/screenshot.png -define histogram:unique-colors=true -format %c histogram:info:")
        # check that the green image displayed somewhere
        image_check = re.match(".*#FF0500.*", displayed_colors, re.S)
        if image_check is None:
          raise Exception("cannot detect the uploaded image on pixelfed page.")

      with subtest("access garage"):
        server.succeed("mc alias set garage ${nodes.server.fediversity.internal.garage.api.url} --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY")
        server.succeed("mc ls garage/pixelfed")

      with subtest("access image in garage"):
        image = server.succeed("mc find garage --regex '\\.png' --ignore '*_thumb.png'")
        image = image.rstrip()
        if image == "":
          raise Exception("image posted to Pixelfed did not get stored in garage")
        server.succeed(f"mc cat {image} >/garage-image.png")
        garage_image_hash = server.succeed("identify -quiet -format '%#' /garage-image.png")
        image_hash = server.succeed("identify -quiet -format '%#' $POST_MEDIA")
        if garage_image_hash != image_hash:
          raise Exception("image stored in garage did not match image uploaded")

      with subtest("Check that image comes from garage"):
        src = server.succeed("su - selenium -c 'selenium-script-get-src ${email} ${password}'")
        if not src.startswith("${nodes.server.fediversity.internal.garage.web.urlForBucket "pixelfed"}"):
          raise Exception("image does not come from garage")
    '';
}
