/**
 * #50 — at mount, `ProjectsView` reconciles its `placements` with the detached
 * view windows already open at the OS level (a panel-only window restored by the
 * OS before the main window mounted). Without this, the Panneaux menu would show
 * such a window as « Fermé ». This exercises the wiring end-to-end through the
 * {@link WindowGateway}; the reconciliation invariants themselves are unit-tested
 * in `viewPlacement.test.ts`.
 */
import { describe, it, expect } from "vitest";
import {
  render,
  screen,
  within,
  waitFor,
  fireEvent,
} from "@testing-library/react";

import {
  MockAgentGateway,
  MockGitGateway,
  MockProfileGateway,
  MockFocusedProjectGateway,
  MockProjectGateway,
  MockSystemGateway,
  MockTemplateGateway,
  MockWindowGateway,
  MockWorkStateGateway,
} from "@/adapters/mock";
import type { Gateways, WindowGateway } from "@/ports";
import { DIProvider } from "@/app/di";
import { ProjectsView } from "./ProjectsView";

async function renderWith(windowGateway: WindowGateway) {
  const project = new MockProjectGateway();
  await project.createProject("alpha", "/p/a");
  const agentGateway = new MockAgentGateway();
  const gateways = {
    system: new MockSystemGateway(),
    project,
    agent: agentGateway,
    profile: new MockProfileGateway(),
    template: new MockTemplateGateway(agentGateway),
    git: new MockGitGateway(),
    workState: new MockWorkStateGateway(),
    window: windowGateway,
    focusedProject: new MockFocusedProjectGateway(),
  } as unknown as Gateways;
  render(
    <DIProvider gateways={gateways}>
      <ProjectsView />
    </DIProvider>,
  );
  fireEvent.click(await screen.findByRole("button", { name: "Open" }));
  await waitFor(() =>
    expect(
      within(screen.getByRole("tablist")).getAllByRole("tab"),
    ).toHaveLength(1),
  );
}

/** Opens « Panneaux → Git » and returns the « Fenêtre détachée » submenu leaf. */
function openGitDetachedLeaf() {
  fireEvent.click(screen.getByRole("button", { name: "Panneaux" }));
  fireEvent.click(screen.getByRole("button", { name: "Git" }));
  return screen.getByRole("button", { name: "Fenêtre détachée" });
}

describe("ProjectsView startup reconciliation (#50)", () => {
  it("marks an already-open detached window as « détaché » at mount", async () => {
    const windowGateway = new MockWindowGateway();
    // A panel-only Git window is already open at the OS level before mount.
    windowGateway.open.add("git");

    await renderWith(windowGateway);

    // The « Fenêtre détachée » leaf reads ACTIVE (●) — not « Fermé ».
    await waitFor(() =>
      expect(openGitDetachedLeaf().textContent).toContain("●"),
    );
  });

  it("does not reconcile when enumeration fails (no ghost detached slot)", async () => {
    const windowGateway = new MockWindowGateway();
    windowGateway.listOpenViewWindows = () =>
      Promise.reject(new Error("boom"));

    await renderWith(windowGateway);

    // Git stays « Fermé »: the detached leaf is not active.
    fireEvent.click(screen.getByRole("button", { name: "Panneaux" }));
    fireEvent.click(screen.getByRole("button", { name: "Git" }));
    await waitFor(() =>
      expect(
        screen.getByRole("button", { name: "Fenêtre détachée" }).textContent,
      ).not.toContain("●"),
    );
  });
});
