import { describe, expect, it } from "vitest";

import type { CustomPluginLayoutCell, PluginAdmin } from "@/domain";
import {
  PluginCommandRegistry,
  PluginLayoutRegistry,
  PluginMenuRegistry,
  PluginRuntimeRegistry,
  type LoadedPlugin,
} from "@/plugins/runtime";
import { resolvePluginLayoutAvailability } from "./layoutAvailability";

function stubPlugin(pluginId: string, layoutTypes: string[]): LoadedPlugin {
  const contributes = {
    menus: [],
    menuItems: [],
    layouts: layoutTypes.map((type) => ({ type, label: type, component: type })),
    mcpServers: [],
  };
  const layouts = new PluginLayoutRegistry(pluginId, new Set(layoutTypes));
  for (const type of layoutTypes) {
    layouts.register({ type, component: () => null });
  }
  return {
    pluginId,
    displayName: pluginId,
    contributes,
    commands: new PluginCommandRegistry(pluginId, new Set()),
    layouts,
    menu: new PluginMenuRegistry(pluginId),
    dispose: async () => {},
  };
}

function cell(overrides: Partial<CustomPluginLayoutCell> = {}): CustomPluginLayoutCell {
  return {
    id: "leaf-1",
    pluginId: "dev.acme.gitgraph",
    layoutType: "dev.acme.gitgraph.layout",
    state: null,
    ...overrides,
  };
}

describe("resolvePluginLayoutAvailability", () => {
  it("is available when the provider is loaded and declares the layout type", () => {
    const registry = new PluginRuntimeRegistry();
    registry.add(stubPlugin("dev.acme.gitgraph", ["dev.acme.gitgraph.layout"]));
    expect(resolvePluginLayoutAvailability(registry, cell())).toBe("available");
  });

  it("is incompatible when the provider is loaded but no longer declares the type", () => {
    const registry = new PluginRuntimeRegistry();
    registry.add(stubPlugin("dev.acme.gitgraph", ["some.other.type"]));
    expect(resolvePluginLayoutAvailability(registry, cell())).toBe("incompatible");
  });

  it("is plugin-missing when the provider is not loaded and not in the admin list", () => {
    const registry = new PluginRuntimeRegistry();
    expect(resolvePluginLayoutAvailability(registry, cell())).toBe("plugin-missing");
  });

  it("is plugin-disabled when the provider is not loaded but known-disabled in the admin list", () => {
    const registry = new PluginRuntimeRegistry();
    const admin: PluginAdmin[] = [
      {
        id: "dev.acme.gitgraph",
        displayName: "Git Graph",
        version: "1.0.0",
        sourceKind: "archive",
        lifecycleState: "disabled",
        enabled: false,
        pendingUninstall: false,
        restartRequired: false,
        trustLevel: "full",
        contributionSummary: { topLevelMenus: 0, menuItems: 0, layouts: 1, mcpServers: 0 },
      },
    ];
    expect(resolvePluginLayoutAvailability(registry, cell(), admin)).toBe("plugin-disabled");
  });
});
