/**
 * F2 — `PluginsPanel` (ticket #43, carnet §10 F2 acceptance criteria): install
 * from archive/directory with pre-install review, full-trust mention visible,
 * enable/disable/uninstall flows, and `restartRequired` rendered.
 */
import { describe, it, expect } from "vitest";
import { render, screen, waitFor, fireEvent, within } from "@testing-library/react";

import { MockPluginGateway, MockSystemGateway } from "@/adapters/mock";
import type { Gateways } from "@/ports";
import { DIProvider } from "@/app/di";
import { PluginsPanel } from "./PluginsPanel";

function renderPanel(plugin?: MockPluginGateway, system?: MockSystemGateway) {
  const p = plugin ?? new MockPluginGateway();
  const s = system ?? new MockSystemGateway();
  const gateways = { plugin: p, system: s } as unknown as Gateways;
  return {
    plugin: p,
    system: s,
    ...render(
      <DIProvider gateways={gateways}>
        <PluginsPanel />
      </DIProvider>,
    ),
  };
}

describe("PluginsPanel", () => {
  it("shows an empty state with no plugins installed", async () => {
    renderPanel();
    expect(await screen.findByText("Aucun plugin installé.")).toBeTruthy();
  });

  it("installs from an archive via the review dialog, mentioning full-trust", async () => {
    renderPanel();
    await screen.findByText("Aucun plugin installé.");

    fireEvent.click(screen.getByRole("button", { name: "Installer depuis une archive…" }));

    const dialog = await screen.findByRole("dialog");
    expect(within(dialog).getByText(/full-trust/)).toBeTruthy();

    fireEvent.click(within(dialog).getByRole("button", { name: "Installer" }));

    // The installed plugin now shows in the list, restart required (carnet §1.4).
    expect(await screen.findByText("mock-plugin")).toBeTruthy();
    expect(screen.getByText("Redémarrage requis")).toBeTruthy();
    expect(screen.getByText("Activé")).toBeTruthy();
  });

  it("disables an installed plugin after confirmation", async () => {
    const plugin = new MockPluginGateway();
    plugin._seedPlugin({
      id: "dev.acme.one",
      displayName: "Acme One",
      version: "1.0.0",
      sourceKind: "archive",
      lifecycleState: "enabled",
      enabled: true,
      pendingUninstall: false,
      restartRequired: false,
      trustLevel: "full",
      contributionSummary: { topLevelMenus: 0, menuItems: 0, layouts: 0, mcpServers: 0 },
    });
    renderPanel(plugin);

    await screen.findByText("Acme One");
    fireEvent.click(screen.getByRole("button", { name: "Désactiver" }));

    const dialog = await screen.findByRole("dialog");
    fireEvent.click(within(dialog).getByRole("button", { name: "Désactiver" }));

    await waitFor(() => expect(screen.getByText("Désactivé")).toBeTruthy());
  });

  it("uninstalls an installed plugin after confirmation", async () => {
    const plugin = new MockPluginGateway();
    plugin._seedPlugin({
      id: "dev.acme.two",
      displayName: "Acme Two",
      version: "1.0.0",
      sourceKind: "directory",
      lifecycleState: "enabled",
      enabled: true,
      pendingUninstall: false,
      restartRequired: false,
      trustLevel: "full",
      contributionSummary: { topLevelMenus: 0, menuItems: 0, layouts: 0, mcpServers: 0 },
    });
    renderPanel(plugin);

    await screen.findByText("Acme Two");
    fireEvent.click(screen.getByRole("button", { name: "Désinstaller" }));

    const dialog = await screen.findByRole("dialog");
    fireEvent.click(within(dialog).getByRole("button", { name: "Désinstaller" }));

    await waitFor(() => expect(screen.queryByText("Acme Two")).toBeNull());
    expect(await screen.findByText("Aucun plugin installé.")).toBeTruthy();
  });
});
