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);
}

const { nextTick } = await import("vue");
const { createTerminalApp } = await import("@simon_he/vue-tui");
const { DimSdkShell, createDimSdkRouter } = await import("../src/dimsdk/index.ts");
const { createErrorGoatChainAgent: createErrorDimSdkAgent } = await import("../src/dimsdk/core/agents/error.ts");

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

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

async function pressKey(
  app: {
    events: { dispatch: (event: unknown) => boolean | void };
    scheduler: { flush: () => void };
  },
  key: string,
  options: Readonly<{ shiftKey?: boolean }> = {},
) {
  app.events.dispatch({ type: "keydown", key, code: key, ...options } as const);
  await flushApp(app);
}

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

describe("dimsdk home keyboard regression", () => {
  it("ArrowUp/Down in TInput does not blank logo/footer", 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."));
    const context = {
      system: "You are DimSdk (mock).",
      cwd: ".",
      env: { DIMCODE_VERSION: "1.1.8" },
    } as const;

    const app = createTerminalApp({
      cols: 120,
      rows: 36,
      component: DimSdkShell as never,
      props: { toolRunner, context, agent },
      defaultStyle: { bg: "black", fg: "whiteBright" },
    });

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

      expect(snapshotText(app)).toContain("Welcome! Quick start:");
      expect(snapshotText(app)).toContain("v1.1.8");

      for (const ch of "abcd") {
        await pressKey(app, ch);
      }
      await pressKey(app, "Enter", { shiftKey: true });
      for (const ch of "efgh") {
        await pressKey(app, ch);
      }
      await pressKey(app, "Enter", { shiftKey: true });
      for (const ch of "ijkl") {
        await pressKey(app, ch);
      }
      await pressKey(app, "Enter", { shiftKey: true });
      for (const ch of "mnop") {
        await pressKey(app, ch);
      }

      expect(snapshotText(app)).toContain("Welcome! Quick start:");
      expect(snapshotText(app)).toContain("v1.1.8");

      await pressKey(app, "ArrowUp");
      await pressKey(app, "ArrowDown");

      expect(snapshotText(app)).toContain("Welcome! Quick start:");
      expect(snapshotText(app)).toContain("v1.1.8");
    } finally {
      app.dispose();
    }
  });
});
