{ lib, pkgs }:
let
  pluginStubs = pkgs.callPackage ../../../utils/plugin-stubs.nix { };

  isByteCompiledFun = # lua
    ''
      -- LuaJIT bytecode header is: ESC L J version
      -- https://github.com/LuaJIT/LuaJIT/blob/v2.1/src/lj_bcdump.h
      -- We are comparing the first three bytes of the file (until version)
      local expected_header = string.char(0x1b, 0x4c, 0x4a)
      local function is_byte_compiled(filename)
        local f = assert(io.open(filename, "rb"))
        local data = assert(f:read(3))
        f:close()
        return data == expected_header
      end

      local function test_rtp_file(name, is_compiled)
        local file = assert(vim.api.nvim_get_runtime_file(name, false)[1], "file " .. name .. " not found in runtime")
        if is_compiled then
          assert(is_byte_compiled(file), name .. " is expected to be byte compiled, but it's not")
        else
          assert(not is_byte_compiled(file), name .. " is not expected to be byte compiled, but it is")
        end
      end

      local function test_lualib_file(func, is_compiled)
        -- Get the source of the func
        local info = debug.getinfo(func, "S")
        -- The source returned by debug.getinfo is prefixed with '@'
        local file = info.source:sub(2)
        assert(vim.uv.fs_stat(file))
        if is_compiled then
          assert(is_byte_compiled(file), file .. " is expected to be byte compiled, but it's not")
        else
          assert(not is_byte_compiled(file), file .. " is not expected to be byte compiled, but it is")
        end
      end

      local function assert_g_var(varname, filename)
        assert(
          vim.g[varname] == true or vim.g[varname] == 1,
          string.format(
            "expected vim.g.%s to be truthy, got %s. File %s isn't executed?",
            varname,
            vim.g[varname],
            filename
          )
        )
      end
    '';

  # In order to know where lua library come from
  # split plugins and libs to avoid lua libraries intersection.
  shortPluginList = with pluginStubs; [
    plugin1
    pluginWithDep4
  ];
  shortPluginNames = [
    "plugin1"
    "plugin_with_dep4"
    "plugin4"
    "plugin3"
  ];
  shortPluginLuaNames = [
    "lib1"
    "lib2"
    # "lib3" # is in both
  ];
  shortLuaList = with pluginStubs; [
    lib4
    libWithDep5
  ];
  shortLuaNames = [
    "lib4"
    "lib_with_dep5"
    "lib5"
    # "lib3" # is in both
  ];
  shortLuaAllNames = shortPluginLuaNames ++ shortLuaNames ++ [ "lib3" ];
  shortChecks =
    pluginStubs.pluginChecksFor shortPluginNames
    + pluginStubs.libChecksFor shortLuaAllNames
    + pluginStubs.pythonChecksFor [
      "yaml"
      "numpy"
    ];
in
# TODO: 2025-07-25 luajit2.1-lib[1-5]-0.0.1 failing to build
# Error: /build/init.lua/lib1-0.0.1-1.rockspec: Unknown field build_dependencies (using rockspec format 1.0)
lib.optionalAttrs false (
  {
    default =
      {
        config,
        lib,
        pkgs,
        ...
      }:
      let
        writeLua = lib.nixvim.builders.writeLuaWith pkgs;
      in
      {
        performance.byteCompileLua.enable = true;

        extraFiles = {
          # By text
          "plugin/extra_file_text.lua".text = "vim.g.extra_file_text = true";
          # By simple source derivation using buildCommand
          "plugin/extra_file_source.lua".source =
            writeLua "extra_file_source.lua" "vim.g.extra_file_source = true";
          # By standard derivation, it needs to execute fixupPhase
          "plugin/extra_file_drv.lua".source = pkgs.stdenvNoCC.mkDerivation {
            name = "extra_file_drv.lua";
            src = pkgs.emptyDirectory;
            buildPhase = ''
              echo "vim.g.extra_file_drv = true" > $out
            '';
          };
          # By path
          "plugin/extra_file_path.lua".source = ./files/file.lua;
          # By string
          "plugin/extra_file_string.lua".source =
            builtins.toFile "extra_file_path.lua" "vim.g.extra_file_string = true";
          # By derivation converted to string
          "plugin/extra_file_drv_string.lua".source = toString (
            writeLua "extra_file_drv_string.lua" "vim.g.extra_file_drv_string = true"
          );
          # Non-lua file
          "plugin/extra_file_non_lua.vim".text = "let g:extra_file_non_lua = 1";
          # Lua file with txt extension won't be byte compiled
          "text.txt".source = writeLua "text.txt" "vim.g.text = true";
        };

        files = {
          "plugin/file.lua" = {
            globals.file_lua = true;
          };
          "plugin/file.vim" = {
            globals.file_vimscript = true;
          };
        };

        extraPlugins = shortPluginList;

        extraLuaPackages = _: shortLuaList;

        extraConfigLua = ''
          -- The test will search for the next string in nixvim-print-init's output: VALIDATING_STRING.
          -- Since this is the comment, it won't appear in byte compiled file.

          vim.g.init_lua = true
        '';

        # Using plugin for the test code to avoid infinite recursion
        extraFiles."plugin/test.lua".text =
          # lua
          ''
            ${isByteCompiledFun}

            ${shortChecks}

            -- vimrc is byte compiled
            local init = vim.env.MYVIMRC or vim.fn.getscriptinfo({name = "init.lua"})[1].name
            assert(is_byte_compiled(init), "MYVIMRC is expected to be byte compiled, but it's not")
            assert_g_var("init_lua", "MYVIMRC")

            -- nixvim-print-init prints text
            local init_content = vim.fn.system("${lib.getExe config.build.printInitPackage}")
            assert(init_content:find("VALIDATING_STRING"), "nixvim-print-init's output is byte compiled")

            local runtime_lua_files = {
              -- lua 'extraFiles' are byte compiled
              { "plugin/extra_file_text.lua", true, "extra_file_text" },
              { "plugin/extra_file_source.lua", true, "extra_file_source" },
              { "plugin/extra_file_drv.lua", true, "extra_file_drv" },
              { "plugin/extra_file_path.lua", true, "extra_file_path" },
              { "plugin/extra_file_string.lua", true, "extra_file_string" },
              { "plugin/extra_file_drv_string.lua", true, "extra_file_drv_string" },
              -- other 'extraFiles'
              { "plugin/extra_file_non_lua.vim", false, "extra_file_non_lua" },
              -- lua 'files' are byte compiled
              { "plugin/file.lua", true, "file_lua" },
              -- other 'files'
              { "plugin/file.vim", false, "file_vimscript" },
            }
            for _, test in ipairs(runtime_lua_files) do
              local file, expected_byte_compiled, varname = unpack(test)
              test_rtp_file(file, expected_byte_compiled)
              -- Runtime plugin scripts are loaded last, so activate each manually before a test
              vim.cmd.runtime(file)
              assert_g_var(varname, file)
            end

            -- Nvim runtime isn't byte compiled by default
            test_rtp_file("lua/vim/lsp.lua", false)

            -- Plugins aren't byte-compiled by default
            ${lib.concatMapStrings (name: ''
              test_rtp_file("lua/${name}/init.lua", false)
              test_rtp_file("plugin/${name}.lua", false)
            '') shortPluginNames}

            -- Lua library isn't byte-compiled by default
            ${lib.concatMapStrings (name: ''
              test_lualib_file(require("${name}").name, false)
            '') shortLuaAllNames}
          '';

      };

    disabled = {
      performance.byteCompileLua.enable = false;

      extraFiles."plugin/test1.lua".text = "vim.opt.tabstop = 2";

      files."plugin/test2.lua".opts.tabstop = 2;

      extraPlugins = shortPluginList;

      extraLuaPackages = _: shortLuaList;

      extraConfigLua = ''
        ${isByteCompiledFun}

        -- Nothing is byte compiled
        -- vimrc
        local init = vim.env.MYVIMRC or vim.fn.getscriptinfo({name = "init.lua"})[1].name
        assert(not is_byte_compiled(init), "MYVIMRC is not expected to be byte compiled, but it is")
        -- extraFiles
        test_rtp_file("plugin/test1.lua", false)
        -- files
        test_rtp_file("plugin/test2.lua", false)
        -- Neovim runtime
        test_rtp_file("lua/vim/lsp.lua", false)
        -- plugins
        test_rtp_file("lua/${builtins.elemAt shortPluginNames 0}/init.lua", false)
        -- lua library
        test_lualib_file(require("${builtins.elemAt shortLuaNames 0}").name, false)
        test_lualib_file(require("${builtins.elemAt shortPluginLuaNames 0}").name, false)
      '';
    };

    init-lua-disabled = {
      performance.byteCompileLua = {
        enable = true;
        initLua = false;
      };

      extraConfigLuaPost = ''
        ${isByteCompiledFun}

        -- vimrc is not byte compiled
        local init = vim.env.MYVIMRC or vim.fn.getscriptinfo({name = "init.lua"})[1].name
        assert(not is_byte_compiled(init), "MYVIMRC is not expected to be byte compiled, but it is")
      '';
    };

    configs-disabled = {
      performance.byteCompileLua = {
        enable = true;
        configs = false;
      };

      extraFiles."plugin/test1.lua".text = "vim.opt.tabstop = 2";

      files."plugin/test2.lua".opts.tabstop = 2;

      extraConfigLuaPost = ''
        ${isByteCompiledFun}

        -- extraFiles
        test_rtp_file("plugin/test1.lua", false)
        -- files
        test_rtp_file("plugin/test2.lua", false)
      '';
    };

    nvim-runtime = {
      performance.byteCompileLua = {
        enable = true;
        nvimRuntime = true;
      };

      extraPlugins = shortPluginList;
      extraLuaPackages = _: shortLuaList;

      extraConfigLuaPost = ''
        ${isByteCompiledFun}

        ${shortChecks}

        -- vim namespace is working
        vim.opt.tabstop = 2
        vim.api.nvim_get_runtime_file("init.lua", false)
        vim.lsp.get_clients()
        vim.treesitter.language.get_filetypes("nix")
        vim.iter({})

        test_rtp_file("lua/vim/lsp.lua", true)
        test_rtp_file("lua/vim/iter.lua", true)
        test_rtp_file("lua/vim/treesitter/query.lua", true)
        test_rtp_file("lua/vim/lsp/buf.lua", true)
        test_rtp_file("plugin/editorconfig.lua", true)
      '';
    };

    # performance.byteCompileLua.luaLib for extraLuaPackages
    lua-lib-extra-lua-packages = {
      performance.byteCompileLua = {
        enable = true;
        luaLib = true;
      };

      extraLuaPackages = _: pluginStubs.libPack;

      extraConfigLuaPost = ''
        ${pluginStubs.libChecks}

        ${isByteCompiledFun}

        -- Lua modules are byte-compiled
        ${lib.concatMapStringsSep "\n" (
          name: "test_lualib_file(require('${name}').name, true)"
        ) pluginStubs.libNames}
      '';
    };

    # performance.byteCompileLua.luaLib for propagatedBuildInputs
    lua-lib-propagated-build-inputs =
      { config, ... }:
      {
        performance.byteCompileLua = {
          enable = true;
          luaLib = true;
        };

        extraPlugins = pluginStubs.pluginPack;

        extraConfigLuaPost = ''
          ${pluginStubs.pluginChecks}

          ${isByteCompiledFun}

          -- Lua modules are byte-compiled
          ${lib.concatMapStringsSep "\n" (
            name: "test_lualib_file(require('${name}').name, true)"
          ) pluginStubs.libNames}

          -- Plugins themselves are not byte-compiled
          ${lib.concatMapStringsSep "\n" (
            name: "test_rtp_file('lua/${name}/init.lua', false)"
          ) pluginStubs.pluginNames}
        '';

        assertions =
          let
            # Get plugins with all dependencies
            getDeps = drv: [ drv ] ++ builtins.concatMap getDeps drv.dependencies or [ ];
            plugins = lib.pipe config.build.plugins [
              (builtins.catAttrs "plugin")
              (builtins.concatMap getDeps)
              lib.unique
            ];
            # Collect both propagatedBuildInputs and requiredLuaModules to one list
            getAllRequiredLuaModules = lib.flip lib.pipe [
              (
                drvs: builtins.catAttrs "propagatedBuildInputs" drvs ++ builtins.catAttrs "requiredLuaModules" drvs
              )
              (builtins.concatMap (deps: deps ++ getAllRequiredLuaModules deps))
              lib.unique
            ];
            allRequiredLuaModules = getAllRequiredLuaModules plugins;
          in
          [
            # Ensure that lua dependencies are byte-compiled recursively
            # by checking that every library is present only once.
            # If there are two different derivations with the same name,
            # then one of them probably isn't byte-compiled.
            {
              assertion = lib.allUnique (map lib.getName allRequiredLuaModules);
              message = ''
                Expected propagatedBuildInputs and requiredLuaModules of all plugins to have unique names.
                Got the following derivations:''\n${lib.concatLines allRequiredLuaModules}
                Possible reasons:
                - not all dependencies are overridden the same way
                - requiredLuaModules are not updated along with propagatedBuildInputs
              '';
            }
          ];
      };
  }
  //
    # Two equal tests, one with combinePlugins.enable = true
    lib.genAttrs
      [
        "plugins"
        "plugins-combined"
      ]
      (name: {
        performance = {
          byteCompileLua = {
            enable = true;
            plugins = true;
          };

          combinePlugins.enable = lib.hasSuffix "combined" name;
        };

        extraPlugins = pluginStubs.pluginPack ++ [
          # A plugin with invalid lua file
          (pluginStubs.mkPlugin "invalid" {
            postInstall = ''
              mkdir $out/ftplugin
              echo "if true then" >$out/ftplugin/invalid.lua
            '';
          })
        ];

        extraConfigLuaPost = ''
          ${pluginStubs.pluginChecks}

          ${isByteCompiledFun}

          -- Plugins are byte-compiled
          ${lib.concatMapStrings (name: ''
            test_rtp_file("lua/${name}/init.lua", true)
            test_rtp_file("plugin/${name}.lua", true)
          '') pluginStubs.pluginNames}

          -- Lua modules aren't byte-compiled
          ${lib.concatMapStrings (name: ''
            test_lualib_file(require("${name}").name, false)
          '') pluginStubs.libNames}

          -- A plugin with invalid file
          ${pluginStubs.pluginChecksFor [ "invalid" ]}
          -- invalid file exists, but isn't byte compiled
          test_rtp_file("ftplugin/invalid.lua", false)
        '';
      })
)
