/**
 * Tests for the LayoutTabs + git-graph layout creation flow.
 *
 * Covers:
 * - The "+" button shows a create-kind dropdown.
 * - Choosing "Git graph" from the dropdown creates a layout with kind=gitGraph.
 * - A ⎇ badge is visible on git-graph layout tabs.
 * - Creating a terminal layout does NOT show the ⎇ badge.
 * - The mock `createLayout` correctly stores the kind.
 */

import { describe, it, expect, vi } from "vitest";
import { render, screen, waitFor, fireEvent } from "@testing-library/react";

import type { Gateways } from "@/ports";
import { MockLayoutGateway, MockAgentGateway, MockTerminalGateway } from "@/adapters/mock";
import { DIProvider } from "@/app/di";
import { PluginRuntimeProvider } from "@/features/plugins";
import {
  PluginCommandRegistry,
  PluginLayoutRegistry,
  PluginMenuRegistry,
  PluginRuntimeRegistry,
  type LoadedPlugin,
} from "@/plugins/runtime";
import { LayoutTabs } from "./LayoutTabs";

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function renderTabs(
  layout: MockLayoutGateway,
  projectId = "p1",
  onActiveLayoutChange = vi.fn(),
  pluginRegistry?: PluginRuntimeRegistry,
) {
  const gateways = {
    layout,
    terminal: new MockTerminalGateway(),
    agent: new MockAgentGateway(),
  } as unknown as Gateways;
  const ui = (
    <DIProvider gateways={gateways}>
      {pluginRegistry ? (
        <PluginRuntimeProvider
          value={{ registry: pluginRegistry, failures: [], pending: [], loading: false }}
        >
          <LayoutTabs projectId={projectId} onActiveLayoutChange={onActiveLayoutChange} />
        </PluginRuntimeProvider>
      ) : (
        <LayoutTabs projectId={projectId} onActiveLayoutChange={onActiveLayoutChange} />
      )}
    </DIProvider>
  );
  return render(ui);
}

function stubPlugin(pluginId: string, displayName: string, layoutType: string): LoadedPlugin {
  const contributes = {
    menus: [],
    menuItems: [],
    layouts: [{ type: layoutType, label: "Android Health", component: "AndroidHealth" }],
    mcpServers: [],
  };
  return {
    pluginId,
    displayName,
    contributes,
    commands: new PluginCommandRegistry(pluginId, new Set()),
    layouts: new PluginLayoutRegistry(pluginId, new Set([layoutType])),
    menu: new PluginMenuRegistry(pluginId),
    dispose: async () => {},
  };
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

describe("LayoutTabs — git graph kind", () => {
  it("+ button shows a dropdown menu with Terminal and Git graph options", async () => {
    const layout = new MockLayoutGateway();
    renderTabs(layout);

    await waitFor(() => {
      expect(screen.getByLabelText("create layout")).toBeTruthy();
    });

    fireEvent.click(screen.getByLabelText("create layout"));

    await waitFor(() => {
      expect(screen.getByLabelText("create terminal layout")).toBeTruthy();
      expect(screen.getByLabelText("create git graph layout")).toBeTruthy();
    });
  });

  it("MockLayoutGateway.createLayout stores kind=gitGraph correctly", async () => {
    const layout = new MockLayoutGateway();
    const { layoutId } = await layout.createLayout("p1", "My Graph", "gitGraph");
    const { layouts } = await layout.listLayouts("p1");
    const created = layouts.find((l) => l.id === layoutId);
    expect(created).toBeDefined();
    expect(created!.kind).toBe("gitGraph");
  });

  it("MockLayoutGateway.createLayout stores plugin origin and creates a plugin layout tree", async () => {
    const layout = new MockLayoutGateway();
    const pluginOrigin = {
      pluginId: "dev.idea.android-plugin",
      layoutType: "idea-android.health",
    };
    const { layoutId } = await layout.createLayout("p1", "Android Health", "plugin", pluginOrigin);
    const { layouts } = await layout.listLayouts("p1");
    const created = layouts.find((l) => l.id === layoutId);
    expect(created).toMatchObject({ kind: "plugin", pluginOrigin });

    const tree = await layout.loadLayout("p1", layoutId);
    expect(tree.root).toMatchObject({
      type: "customPluginLayout",
      node: {
        pluginId: "dev.idea.android-plugin",
        layoutType: "idea-android.health",
        state: null,
      },
    });
  });

  it("choosing a plugin layout creates and activates a plugin layout without the old blocking notice", async () => {
    const layout = new MockLayoutGateway();
    const registry = new PluginRuntimeRegistry();
    registry.add(stubPlugin("dev.idea.android-plugin", "Android", "idea-android.health"));
    const onActiveLayoutChange = vi.fn();
    renderTabs(layout, "p1", onActiveLayoutChange, registry);

    await waitFor(() => {
      expect(screen.getByLabelText("create layout")).toBeTruthy();
    });

    fireEvent.click(screen.getByLabelText("create layout"));
    fireEvent.click(await screen.findByRole("menuitem", { name: /Android Health/ }));

    await waitFor(() => {
      expect(screen.getByRole("tab", { name: "Android Health" })).toBeTruthy();
      expect(onActiveLayoutChange).toHaveBeenCalledWith(
        expect.objectContaining({
          name: "Android Health",
          kind: "plugin",
          pluginOrigin: {
            pluginId: "dev.idea.android-plugin",
            layoutType: "idea-android.health",
          },
        }),
      );
    });
    expect(screen.queryByText(/extension backend pas encore livrée/i)).toBeNull();
  });

  it("MockLayoutGateway.createLayout defaults to kind=terminal", async () => {
    const layout = new MockLayoutGateway();
    const { layoutId } = await layout.createLayout("p1", "My Terminal");
    const { layouts } = await layout.listLayouts("p1");
    const created = layouts.find((l) => l.id === layoutId);
    expect(created!.kind).toBe("terminal");
  });

  it("git graph tab shows the ⎇ badge", async () => {
    const layout = new MockLayoutGateway();
    // Seed a git-graph layout directly.
    await layout.createLayout("p1", "Graph Tab", "gitGraph");
    renderTabs(layout);

    await waitFor(() => {
      // The aria-label "git graph layout" should be present.
      expect(screen.getByLabelText("git graph layout")).toBeTruthy();
    });
  });

  it("terminal tab does NOT show the ⎇ badge", async () => {
    const layout = new MockLayoutGateway();
    // Only the default "terminal" layout.
    renderTabs(layout);

    await waitFor(() => {
      expect(screen.getByText("Default")).toBeTruthy();
    });

    expect(screen.queryByLabelText("git graph layout")).toBeNull();
  });
});
