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

if (!(globalThis as any).document) {
  const { Window } = await import("happy-dom");
  const window = new Window();
  (globalThis as any).window = window;
  (globalThis as any).document = window.document;
  Object.defineProperty(globalThis, "navigator", {
    configurable: true,
    value: window.navigator,
  });
  (globalThis as any).Node = window.Node;
  (globalThis as any).Element = window.Element;
  (globalThis as any).HTMLElement = window.HTMLElement;
  (globalThis as any).SVGElement = window.SVGElement;
  (globalThis as any).Event = window.Event;
  (globalThis as any).CustomEvent = window.CustomEvent;
  (globalThis as any).MouseEvent = window.MouseEvent;
  (globalThis as any).KeyboardEvent = window.KeyboardEvent;
  (globalThis as any).getComputedStyle = window.getComputedStyle.bind(window);
}

(globalThis as any).getSelection = () => ({ toString: () => "" });

globalThis.requestAnimationFrame = ((cb: FrameRequestCallback) => {
  cb(0);
  return 1;
}) as typeof globalThis.requestAnimationFrame;
globalThis.cancelAnimationFrame = (() => {}) as typeof globalThis.cancelAnimationFrame;

const { defineComponent, h, nextTick } = await import("vue");
const { createTerminalApp, TText, TView } = await import("@simon_he/vue-tui");
const { createErrorGoatChainAgent: createErrorDimSdkAgent } = await import("../src/dimsdk/core/agents/error.ts");
const { requestExit } = await import("../src/dimsdk/cli/exit-controller.ts");
const { DimSdkShell, createDimSdkRouter } = await import("../src/dimsdk/index.ts");
const { DimSdkExitAppDialog } = await import("../src/dimsdk/ui/components/ExitAppDialog.ts");

async function flushApp(app: {
  scheduler: { flush: () => void };
}) {
  await nextTick();
  await nextTick();
  app.scheduler.flush();
}

function snapshotText(app: {
  terminal: { snapshot: () => { lines: string[] } };
}): string {
  return app.terminal.snapshot().lines.join("\n");
}

describe("exit app dialog layout", () => {
  it("renders the full busy-exit copy above a full-screen sibling view", async () => {
    const App = defineComponent({
      name: "ExitAppDialogLayoutApp",
      setup() {
        return () =>
          h("div", null, [
            h(TView, { x: 0, y: 0, w: 90, h: 24 }, () => [
              h(TText, { x: 0, y: 0, value: "background top" }),
              h(TText, { x: 0, y: 23, value: "background bottom" }),
            ]),
            h(DimSdkExitAppDialog as any, {
              modelValue: true,
              reason: "Agent is still responding",
              onExit: () => {},
              "onUpdate:modelValue": () => {},
            }),
          ]);
      },
    });

    const app = createTerminalApp({
      cols: 90,
      rows: 24,
      component: App as never,
      defaultStyle: { fg: "whiteBright", bg: "black" },
    });

    try {
      app.mount();
      await flushApp(app);

      const snapshot = snapshotText(app);
      expect(snapshot).toContain("Exit DimCode");
      expect(snapshot).toContain("Exit now?");
      expect(snapshot).toContain("still in progress");
      expect(snapshot).toContain("Reason: Agent is still responding");
      expect(snapshot).toContain("[ Exit ]");
    } finally {
      app.dispose();
    }
  });

  it("renders the full busy-exit copy from the shell-level Ctrl+C flow", async () => {
    const toolRunner = async () => ({
      id: "tool",
      status: "error" as const,
      output: "Tool execution is disabled in this test.",
    });
    const agent = createErrorDimSdkAgent(new Error("Agent is disabled in this test."));
    let storeRef: any;

    const app = createTerminalApp({
      cols: 100,
      rows: 20,
      component: DimSdkShell as never,
      props: {
        toolRunner,
        context: {
          system: "You are best-agent running in an exit-dialog test.",
          cwd: ".",
          env: { DIMCODE_VERSION: "0.0.0" },
        },
        agent,
        onStoreCreated: (store: any) => {
          storeRef = store;
          store.state.runningAgentRound = true;
        },
      },
      defaultStyle: { fg: "whiteBright", bg: "black" },
    });

    try {
      app.app.use(createDimSdkRouter({ initialRoute: "chat", mode: "cli" }) as never);
      app.mount();
      await flushApp(app);

      expect(storeRef).toBeTruthy();

      requestExit();
      await flushApp(app);

      const snapshot = snapshotText(app);
      expect(snapshot).toContain("Exit DimCode");
      expect(snapshot).toContain("Exit now?");
      expect(snapshot).toContain("still in progress");
      expect(snapshot).toContain("Reason: Agent is still responding");
      expect(snapshot).toContain("[ Exit ]");
    } finally {
      app.dispose();
    }
  });
});
