/**
 * #50 — startup reconciliation of `placements` with the detached view windows
 * already open at the OS level. Unit-tests the pure `isDetachablePanel` guard
 * and `reconcileDetachedWindows`, covering every Architect invariant:
 * only-visible, known-detachable-only (projects/unknown excluded), and the
 * no-clobber rule (never overwrite a non-closed placement).
 */
import { describe, it, expect } from "vitest";

import type { ViewWindowSnapshot } from "@/ports";
import {
  isDetachablePanel,
  reconcileDetachedWindows,
  type ViewPlacements,
} from "./viewPlacement";

const snap = (
  panel: string,
  visible = true,
): ViewWindowSnapshot => ({ panel, label: panel, visible });

describe("isDetachablePanel (#50)", () => {
  it("accepts every known panel except projects", () => {
    expect(isDetachablePanel("git")).toBe(true);
    expect(isDetachablePanel("tickets")).toBe(true);
    expect(isDetachablePanel("memory")).toBe(true);
  });

  it("excludes projects (main-window-only chrome) and unknown panels", () => {
    expect(isDetachablePanel("projects")).toBe(false);
    expect(isDetachablePanel("bogus")).toBe(false);
    expect(isDetachablePanel("")).toBe(false);
  });
});

describe("reconcileDetachedWindows (#50)", () => {
  it("marks a visible detachable snapshot as detached from an empty state", () => {
    const next = reconcileDetachedWindows({}, [snap("git")]);
    expect(next).toEqual({ git: "detached" });
  });

  it("reconciles several panels at once", () => {
    const next = reconcileDetachedWindows({}, [snap("git"), snap("tickets")]);
    expect(next).toEqual({ git: "detached", tickets: "detached" });
  });

  it("ignores non-visible snapshots", () => {
    const prev: ViewPlacements = {};
    const next = reconcileDetachedWindows(prev, [snap("git", false)]);
    expect(next).toBe(prev); // referentially unchanged
  });

  it("excludes the projects panel", () => {
    const prev: ViewPlacements = {};
    const next = reconcileDetachedWindows(prev, [snap("projects")]);
    expect(next).toBe(prev);
  });

  it("ignores unknown panel ids", () => {
    const prev: ViewPlacements = {};
    const next = reconcileDetachedWindows(prev, [snap("bogus")]);
    expect(next).toBe(prev);
  });

  it("never clobbers a non-closed placement (floating/dock/detached preserved)", () => {
    const prev: ViewPlacements = {
      git: "floating",
      tickets: { dock: "left" },
      memory: "detached",
    };
    const next = reconcileDetachedWindows(prev, [
      snap("git"),
      snap("tickets"),
      snap("memory"),
    ]);
    expect(next).toBe(prev); // nothing changed → same reference
  });

  it("reconciles only the closed panels, leaving others intact", () => {
    const prev: ViewPlacements = { git: "floating" };
    const next = reconcileDetachedWindows(prev, [snap("git"), snap("agents")]);
    expect(next).toEqual({ git: "floating", agents: "detached" });
  });

  it("returns the same reference when there is nothing to reconcile", () => {
    const prev: ViewPlacements = {};
    expect(reconcileDetachedWindows(prev, [])).toBe(prev);
  });
});
