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

  # Assertion for a number of plugins of given type defined in nvimPackage.packpathDirs
  expectNPlugins =
    config: type: n:
    let
      # 'build.extraFiles' must not be combined, so exclude it from counting
      plugins = builtins.filter (
        p: lib.getName p != lib.getName config.build.extraFiles
      ) config.build.nvimPackage.packpathDirs.myNeovimPackages.${type};
      numPlugins = builtins.length plugins;
    in
    {
      assertion = numPlugins == n;
      message = "Expected ${toString n} '${type}' plugins defined in 'nvimPackage.packpathDirs', got ${toString numPlugins}: ${
        lib.concatMapStringsSep ", " lib.getName plugins
      }.";
    };
  # Assertion that exactly one start plugin is defined in nvimPackage.packpathDirs
  expectOneStartPlugin = config: expectNPlugins config "start" 1;
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 (
  {
    # Test basic functionality
    default =
      { config, ... }:
      {
        performance.combinePlugins.enable = true;
        extraPlugins = pluginStubs.pluginPack;
        extraConfigLuaPost = ''
          ${pluginStubs.pluginChecks}

          -- No separate plugin entry in vim.api.nvim_list_runtime_paths()
          ${lib.concatMapStrings (
            name: # lua
            ''
              assert(not vim.iter(vim.api.nvim_list_runtime_paths()):any(function(entry)
                return entry:find("${name}", 1, true)
              end), "plugin '${name}' found in runtime, expected to be combined")
            '') pluginStubs.pluginNames}
        '';
        assertions = [
          (expectOneStartPlugin config)
        ];
      };

    # Test disabled option
    disabled =
      { config, ... }:
      {
        performance.combinePlugins.enable = false;
        extraPlugins = pluginStubs.pluginPack;
        extraConfigLuaPost = lib.concatMapStringsSep "\n" (
          name:
          # lua
          ''
            -- Separate plugin entry in vim.api.nvim_list_runtime_paths()
            assert(vim.iter(vim.api.nvim_list_runtime_paths()):any(function(entry)
              return entry:find("${name}", 1, true)
            end), "plugin '${name}' isn't found in runtime as a separate entry, expected not to be combined")
          '') pluginStubs.pluginNames;
        assertions = [
          (expectNPlugins config "start" (builtins.length pluginStubs.pluginPack))
        ];
      };

    # Test that pathsToLink option works
    paths-to-link =
      { config, ... }:
      {
        performance.combinePlugins = {
          enable = true;
          pathsToLink = [ "/_extra" ];
        };
        extraPlugins = [
          # A plugin with extra directory
          (pluginStubs.mkPlugin "extra" {
            postInstall = ''
              mkdir $out/_extra
              touch $out/_extra/test
            '';
          })
        ];
        extraConfigLuaPost = ''
          ${pluginStubs.pluginChecksFor [ "extra" ]}

          -- Test file is in runtime
          assert(
            vim.api.nvim_get_runtime_file("_extra/test", false)[1],
            "'_extra/test' file isn't found in runtime, expected to be found"
          )
        '';
        assertions = [
          (expectOneStartPlugin config)
        ];
      };

    # Test that optional plugins are handled
    optional-plugins =
      { config, ... }:
      {
        performance.combinePlugins.enable = true;
        extraPlugins = with pluginStubs; [
          # Start plugins
          plugin1
          plugin3
          # Optional plugin
          {
            plugin = plugin2;
            optional = true;
          }
          # Optional plugin with dependencies on plugin3 and plugin4
          # Dependencies should not be duplicated
          {
            plugin = pluginWithDep4;
            optional = true;
          }
        ];
        extraConfigLuaPost = ''
          -- Start plugins are working. Dependencies of the optional plugins are also available.
          ${pluginStubs.pluginChecksFor [
            "plugin1"
            "plugin3"
            "plugin4" # Dependency of the optional plugin
          ]}

          -- Lua libraries are available. Libs of the optional plugins are also available.
          ${pluginStubs.libChecksFor [
            "lib1"
            "lib2" # Dependency of the optional plugin
            "lib3"
          ]}

          ${lib.concatMapStrings
            (
              name: # lua
              ''
                -- Optional plugin is not loadable
                local ok = pcall(require, "${name}")
                assert(not ok, "${name} is loadable, expected it to be an opt plugin")

                -- Load plugin
                vim.cmd.packadd("${name}")

                -- Now opt plugin is working
                ${pluginStubs.pluginChecksFor [ name ]}
              '')
            [
              "plugin2"
              "plugin_with_dep4"
            ]
          }

          -- Only one copy of dependent plugin should be available
          ${lib.concatMapStrings
            (
              name: # lua
              ''
                local num_plugins = #vim.api.nvim_get_runtime_file("lua/${name}/init.lua", true)
                assert(num_plugins == 1, "expected 1 copy of ${name}, got " .. num_plugins)
              '')
            [
              "plugin3"
              "plugin4"
            ]
          }
        '';
        assertions = [
          (expectOneStartPlugin config)
          # plugin2 plugin_with_dep4
          (expectNPlugins config "opt" 2)
        ];
      };

    # Test that plugin configs are handled
    configs =
      { config, ... }:
      {
        performance.combinePlugins.enable = true;
        extraPlugins = with pluginStubs; [
          # A plugin without config
          plugin1
          # A plugin with config
          {
            plugin = plugin2;
            config = "let g:plugin2_var = 1";
          }
          # Optional plugin with config
          {
            plugin = plugin3;
            optional = true;
            config = "let g:plugin3_var = 1";
          }
        ];
        extraConfigLuaPost = ''
          -- Configs are evaluated
          assert(vim.g.plugin2_var == 1, "plugin2's config isn't evaluated")
          assert(vim.g.plugin3_var == 1, "plugin3's config isn't evaluated")
        '';
        assertions = [
          (expectOneStartPlugin config)
        ];
      };

    # Test if plenary.filetype is working
    plenary-nvim = {
      performance.combinePlugins.enable = true;
      extraPlugins = [ pkgs.vimPlugins.plenary-nvim ];
      extraConfigLuaPost = ''
        -- Plenary filetype detection is usable
        assert(require("plenary.filetype").detect(".bashrc") == "sh", "plenary.filetype is not working")
      '';
    };
  }
  //
    # Test that config.build.extraFiles is not combined
    # with or without byteCompileLua.enable = true
    lib.genAttrs [ "files-plugin" "files-plugin-byte-compiled" ] (
      name:
      { config, ... }:
      {
        performance = {
          combinePlugins.enable = true;
          byteCompileLua = lib.optionalAttrs (lib.hasSuffix "byte-compiled" name) {
            enable = true;
            plugins = true;
          };
        };
        extraPlugins = with pluginStubs; [
          plugin1
          plugin2
        ];
        # Ensure that build.extraFiles is added to extraPlugins
        wrapRc = true;
        # Extra user files colliding with plugins
        extraFiles = {
          "lua/plugin1/init.lua".text = "return 1";
        };
        # Another form of user files
        files = {
          "lua/plugin2/init.lua" = {
            extraConfigLua = "return 1";
          };
        };
        extraConfigLuaPost = ''
          for _, file in ipairs({"lua/plugin1/init.lua", "lua/plugin2/init.lua"}) do
            local paths_found = vim.api.nvim_get_runtime_file(file, true)
            local num_found = #paths_found

            -- Both plugin and user version are available
            assert(num_found == 2, "expected exactly 2 versions of '" .. file .. "', got " .. num_found)

            -- First found file is from build.extraFiles
            assert(
              paths_found[1]:find("${lib.getName config.build.extraFiles}", 1, true),
              "expected first found '" .. file .. "' to be from build.extraFiles, got " .. paths_found[1]
            )
          end
        '';
        assertions = [
          (expectOneStartPlugin config)
        ];
      }
    )
  //
    # Test that standalonePlugins option works
    # with or without byteCompileLua.enable = true
    lib.genAttrs [ "standalone-plugins" "standalone-plugins-byte-compiled" ] (
      name:
      { config, ... }:
      let
        standalonePlugins = [
          # By plugin name
          "plugin1"
          # By package itself. Its dependency, plugin4, not in this list, so will be combined
          pluginStubs.pluginWithDep4
          # Dependency of other plugin
          "plugin5"
          # Both dependency and top-level plugin
          "plugin3"
        ];
      in
      {
        performance = {
          combinePlugins = {
            enable = true;
            inherit standalonePlugins;
          };
          byteCompileLua = lib.optionalAttrs (lib.hasSuffix "byte-compiled" name) {
            enable = true;
            plugins = true;
          };
        };
        extraPlugins = pluginStubs.pluginPack;
        extraConfigLuaPost = ''
          ${pluginStubs.pluginChecks}

          ${lib.concatMapStringsSep "\n" (
            name:
            let
              isStandalone = builtins.elem name (
                map (x: if builtins.isString x then x else lib.getName x) standalonePlugins
              );
              expectedText = if isStandalone then "standalone" else "combined";
            in
            # lua
            ''
              -- Check that ${name} plugin is ${expectedText}
              local paths = vim.api.nvim_get_runtime_file("lua/${name}", true)
              -- Plugins shouldn't be duplicated
              assert(#paths == 1, "expected exactly 1 copy of '${name}' in runtime, got ", #paths)
              -- Test if plugin is standalone. This matches directory name before '/lua/'.
              local is_standalone = paths[1]:match("^(.+)/lua/"):find("${name}", 1, true) ~= nil
              assert(
                  is_standalone == ${lib.nixvim.toLuaObject isStandalone},
                  "expected '${name}' to be ${expectedText}, found path: " .. paths[1]
              )
            ''
          ) pluginStubs.pluginNames}
        '';
        assertions = [
          # plugin-pack and 'standalonePlugins'
          (expectNPlugins config "start" (builtins.length standalonePlugins + 1))
        ];
      }
    )
)
