const test = require("node:test");
const assert = require("node:assert/strict");

const {
  buildAppMenu,
  clampWindowOpacity,
  applyWindowOpacity,
  isWindowUsable,
  registerMainWindow,
  registerWindowHandlers,
  resolveSettingsWindowBounds,
  restoreWindowInputFocus,
  requestWindowCommandClose,
  sendWhenRendererReady,
  shouldCloseWindowFromInput,
  unregisterMainWindow,
} = require("./windowManager.cjs");
const { createMainWindowApi } = require("./windowManager/mainWindow.cjs");

function createWindowStub({ destroyed = false, webContents } = {}) {
  return {
    isDestroyed() {
      return destroyed;
    },
    isVisible() {
      return true;
    },
    webContents,
  };
}

test("clampWindowOpacity keeps values within 0.5 and 1", () => {
  assert.equal(clampWindowOpacity(1), 1);
  assert.equal(clampWindowOpacity(0.85), 0.85);
  assert.equal(clampWindowOpacity(0.3), 0.5);
  assert.equal(clampWindowOpacity(1.5), 1);
  assert.equal(clampWindowOpacity("bad"), 1);
});

test("applyWindowOpacity clamps and applies to registered main windows", () => {
  const opacityCalls = [];
  const win = {
    isDestroyed() {
      return false;
    },
    setOpacity(value) {
      opacityCalls.push(value);
    },
    webContents: {
      id: 901,
      isDestroyed() {
        return false;
      },
    },
  };
  registerMainWindow(win);

  try {
    assert.equal(applyWindowOpacity(0.85), 0.85);
    assert.deepEqual(opacityCalls, [0.85]);

    assert.equal(applyWindowOpacity(0.2), 0.5);
    assert.deepEqual(opacityCalls, [0.85, 0.5]);
  } finally {
    unregisterMainWindow(win);
    applyWindowOpacity(1);
  }
});

test("isWindowUsable returns false when webContents is crashed", () => {
  const win = createWindowStub({
    webContents: {
      isDestroyed() {
        return false;
      },
      isCrashed() {
        return true;
      },
    },
  });

  assert.equal(isWindowUsable(win), false);
});

test("isWindowUsable returns true for a healthy live window", () => {
  const win = createWindowStub({
    webContents: {
      isDestroyed() {
        return false;
      },
      isCrashed() {
        return false;
      },
    },
  });

  assert.equal(isWindowUsable(win), true);
});

test("isWindowUsable can require a visible window", () => {
  const hiddenWin = {
    ...createWindowStub({
      webContents: {
        isDestroyed() {
          return false;
        },
        isCrashed() {
          return false;
        },
      },
    }),
    isVisible() {
      return false;
    },
  };

  assert.equal(isWindowUsable(hiddenWin, { requireVisible: true }), false);
  assert.equal(isWindowUsable(hiddenWin, { requireVisible: false }), true);
});

test("restoreWindowInputFocus focuses the window and renderer on Windows without showing hidden windows", () => {
  const calls = [];
  const win = {
    isDestroyed() {
      return false;
    },
    show() {
      calls.push("show");
    },
    focus() {
      calls.push("focus");
    },
    setAlwaysOnTop(value) {
      calls.push(`alwaysOnTop:${value}`);
    },
    webContents: {
      isDestroyed() {
        return false;
      },
      focus() {
        calls.push("webContents.focus");
      },
    },
  };

  const restored = restoreWindowInputFocus(win, { platform: "win32" });

  assert.equal(restored, true);
  assert.deepEqual(calls, [
    "alwaysOnTop:true",
    "focus",
    "alwaysOnTop:false",
    "webContents.focus",
  ]);
});

test("restoreWindowInputFocus clears Windows always-on-top even if window focus throws", () => {
  const calls = [];
  const win = {
    isDestroyed() {
      return false;
    },
    focus() {
      calls.push("focus");
      throw new Error("focus failed");
    },
    setAlwaysOnTop(value) {
      calls.push(`alwaysOnTop:${value}`);
    },
    webContents: {
      isDestroyed() {
        return false;
      },
      focus() {
        calls.push("webContents.focus");
      },
    },
  };

  const restored = restoreWindowInputFocus(win, { platform: "win32" });

  assert.equal(restored, true);
  assert.deepEqual(calls, [
    "alwaysOnTop:true",
    "focus",
    "alwaysOnTop:false",
    "webContents.focus",
  ]);
});

test("restoreWindowInputFocus can show the window when requested", () => {
  const calls = [];
  const win = {
    isDestroyed() {
      return false;
    },
    show() {
      calls.push("show");
    },
    focus() {
      calls.push("focus");
    },
    webContents: {
      isDestroyed() {
        return false;
      },
      focus() {
        calls.push("webContents.focus");
      },
    },
  };

  const restored = restoreWindowInputFocus(win, { platform: "darwin", show: true });

  assert.equal(restored, true);
  assert.deepEqual(calls, ["show", "focus", "webContents.focus"]);
});

test("buildAppMenu closes a non-app window directly when Cmd+W is invoked", () => {
  let capturedTemplate = null;
  const Menu = {
    buildFromTemplate(template) {
      capturedTemplate = template;
      return { template };
    },
  };

  buildAppMenu(Menu, { name: "Netcatty" }, true);

  const windowMenu = capturedTemplate.find((item) => item.label === "Window");
  assert.ok(windowMenu);
  const closeItem = windowMenu.submenu.find((item) => item.accelerator === "CommandOrControl+W");
  assert.ok(closeItem);
  assert.equal(closeItem.label, "Close Window");

  const calls = [];
  closeItem.click(null, {
    isDestroyed() { return false; },
    close() {
      calls.push("close");
    },
    webContents: {
      isDestroyed() { return false; },
      send(channel) {
        calls.push(`send:${channel}`);
      },
    },
  });

  assert.deepEqual(calls, ["close"]);
});

test("buildAppMenu sends Cmd+W to any registered main window renderer", () => {
  let capturedTemplate = null;
  const Menu = {
    buildFromTemplate(template) {
      capturedTemplate = template;
      return { template };
    },
  };

  const calls = [];
  const firstMainWindow = {
    isDestroyed() { return false; },
    on() {},
    webContents: {
      isDestroyed() { return false; },
      send(channel) {
        calls.push(`first:${channel}`);
      },
    },
  };
  const secondMainWindow = {
    isDestroyed() { return false; },
    on() {},
    webContents: {
      isDestroyed() { return false; },
      send(channel) {
        calls.push(`second:${channel}`);
      },
    },
  };

  registerMainWindow(firstMainWindow);
  registerMainWindow(secondMainWindow);
  try {
    buildAppMenu(Menu, { name: "Netcatty" }, true);
    const windowMenu = capturedTemplate.find((item) => item.label === "Window");
    const closeItem = windowMenu.submenu.find((item) => item.accelerator === "CommandOrControl+W");

    closeItem.click(null, firstMainWindow);

    assert.deepEqual(calls, ["first:netcatty:window:command-close"]);
  } finally {
    unregisterMainWindow(firstMainWindow);
    unregisterMainWindow(secondMainWindow);
  }
});

test("buildAppMenu keeps app reload click-only so custom reload-like shortcuts reach the renderer", () => {
  let capturedTemplate = null;
  const Menu = {
    buildFromTemplate(template) {
      capturedTemplate = template;
      return { template };
    },
  };

  buildAppMenu(Menu, { name: "Netcatty" }, false);

  const viewMenu = capturedTemplate.find((item) => item.label === "View");
  assert.ok(viewMenu);
  assert.equal(viewMenu.submenu.some((item) => item.role === "reload"), false);
  assert.equal(viewMenu.submenu.some((item) => item.role === "forceReload"), false);
  assert.equal(viewMenu.submenu.some((item) => item.accelerator === "CommandOrControl+R"), false);
  assert.equal(viewMenu.submenu.some((item) => item.accelerator === "CommandOrControl+Shift+R"), false);

  const reloadItem = viewMenu.submenu.find((item) => item.label === "Reload");
  assert.ok(reloadItem);
  assert.equal(reloadItem.role, undefined);
  assert.equal(reloadItem.accelerator, undefined);

  const calls = [];
  reloadItem.click(null, {
    reload() {
      calls.push("reload");
    },
  });

  assert.deepEqual(calls, ["reload"]);
});

test("requestWindowCommandClose sends command-close to renderer-capable windows", () => {
  const sentChannels = [];
  const win = {
    isDestroyed() { return false; },
    webContents: {
      isDestroyed() { return false; },
      send(channel) {
        sentChannels.push(channel);
      },
    },
  };

  assert.equal(requestWindowCommandClose(win), true);
  assert.deepEqual(sentChannels, ["netcatty:window:command-close"]);
});

test("shouldCloseWindowFromInput only matches macOS Command+W keydown", () => {
  assert.equal(shouldCloseWindowFromInput({ type: "keyDown", meta: true, key: "w" }), true);
  assert.equal(shouldCloseWindowFromInput({ type: "keyDown", meta: true, key: "W" }), true);
  assert.equal(shouldCloseWindowFromInput({ type: "keyUp", meta: true, key: "w" }), false);
  assert.equal(shouldCloseWindowFromInput({ type: "keyDown", control: true, key: "w" }), false);
  assert.equal(shouldCloseWindowFromInput({ type: "keyDown", meta: true, shift: true, key: "w" }), false);
});

test("main window asks renderer to close tabs from macOS Command+W before-input-event", async () => {
  let beforeInputHandler = null;
  const commandCloseRequests = [];

  class BrowserWindowStub {
    constructor() {
      this.webContents = {
        id: 1,
        on(channel, handler) {
          if (channel === "before-input-event") beforeInputHandler = handler;
        },
        once() {},
        isDestroyed() {
          return false;
        },
        isCrashed() {
          return false;
        },
        setIgnoreMenuShortcuts() {},
        setWindowOpenHandler() {},
        openDevTools() {},
      };
    }

    on() {}
    once() {}
    isDestroyed() { return false; }
    isMaximized() { return false; }
    isFullScreen() { return false; }
    getBounds() { return { x: 0, y: 0, width: 1400, height: 900 }; }
    setBackgroundColor() {}
    setOpacity() {}
    async loadURL() {}
    close() {}
  }

  const api = createMainWindowApi({
    mainWindow: null,
    electronApp: null,
    currentTheme: "light",
    isQuitting: false,
    pendingWindowStateWrite: null,
    queuedWindowState: null,
    windowStateCloseRequested: false,
    DEFAULT_WINDOW_WIDTH: 1400,
    DEFAULT_WINDOW_HEIGHT: 900,
    MIN_WINDOW_WIDTH: 1100,
    MIN_WINDOW_HEIGHT: 640,
    V8_CACHE_OPTIONS: "bypassHeatCheck",
    THEME_COLORS: { light: { background: "#fff" } },
    unhealthyWebContentsIds: new Set(),
    rendererReadySeenByWebContentsId: new Set(),
    __dirname,
    URL,
    require,
    console,
    setTimeout,
    clearTimeout,
    getGlobalShortcutBridge() {
      return { handleWindowClose: () => false };
    },
    debugLog() {},
    resolveFrontendBackgroundColor() { return null; },
    loadWindowState() { return null; },
    getDevRendererBaseUrl(url) { return url; },
    getWindowBoundsState() { return null; },
    queueWindowStateSave() {},
    saveWindowStateSync() {},
    setupDeferredShow() {},
    createExternalOnlyWindowOpenHandler() { return {}; },
    createAppWindowOpenHandler() { return {}; },
    attachOAuthLoadingOverlay() {},
    registerWindowHandlers() {},
    requestWindowCommandClose(win) {
      commandCloseRequests.push(win);
      return true;
    },
    shouldCloseWindowFromInput,
    applyWindowOpacityToWindow() {},
    closeSettingsWindow() {},
    hideSettingsWindow() {},
  });

  await api.createWindow(
    {
      BrowserWindow: BrowserWindowStub,
      nativeTheme: {},
      app: {},
      screen: {},
      shell: {},
      ipcMain: {},
    },
    {
      preload: "/tmp/preload.cjs",
      devServerUrl: "http://localhost:5173",
      isDev: true,
      appIcon: null,
      isMac: true,
      electronDir: __dirname,
    },
  );

  let prevented = false;
  beforeInputHandler({ preventDefault: () => { prevented = true; } }, {
    type: "keyDown",
    meta: true,
    key: "w",
  });

  assert.equal(prevented, true);
  assert.equal(commandCloseRequests.length, 1);
});

test("main window leaves primary-modifier reload-like shortcuts available to renderer handlers", async () => {
  let beforeInputHandler = null;
  const ignoreMenuShortcutValues = [];

  class BrowserWindowStub {
    constructor() {
      this.webContents = {
        id: 1,
        on(channel, handler) {
          if (channel === "before-input-event") beforeInputHandler = handler;
        },
        once() {},
        isDestroyed() {
          return false;
        },
        isCrashed() {
          return false;
        },
        setIgnoreMenuShortcuts(value) {
          ignoreMenuShortcutValues.push(value);
        },
        setWindowOpenHandler() {},
        openDevTools() {},
      };
    }

    on() {}
    once() {}
    isDestroyed() { return false; }
    isMaximized() { return false; }
    isFullScreen() { return false; }
    getBounds() { return { x: 0, y: 0, width: 1400, height: 900 }; }
    setBackgroundColor() {}
    setOpacity() {}
    async loadURL() {}
    close() {}
  }

  const api = createMainWindowApi({
    mainWindow: null,
    electronApp: null,
    currentTheme: "light",
    isQuitting: false,
    pendingWindowStateWrite: null,
    queuedWindowState: null,
    windowStateCloseRequested: false,
    DEFAULT_WINDOW_WIDTH: 1400,
    DEFAULT_WINDOW_HEIGHT: 900,
    MIN_WINDOW_WIDTH: 1100,
    MIN_WINDOW_HEIGHT: 640,
    V8_CACHE_OPTIONS: "bypassHeatCheck",
    THEME_COLORS: { light: { background: "#fff" } },
    unhealthyWebContentsIds: new Set(),
    rendererReadySeenByWebContentsId: new Set(),
    __dirname,
    URL,
    require,
    console,
    setTimeout,
    clearTimeout,
    getGlobalShortcutBridge() {
      return { handleWindowClose: () => false };
    },
    debugLog() {},
    resolveFrontendBackgroundColor() { return null; },
    loadWindowState() { return null; },
    getDevRendererBaseUrl(url) { return url; },
    getWindowBoundsState() { return null; },
    queueWindowStateSave() {},
    saveWindowStateSync() {},
    setupDeferredShow() {},
    createExternalOnlyWindowOpenHandler() { return {}; },
    createAppWindowOpenHandler() { return {}; },
    attachOAuthLoadingOverlay() {},
    registerWindowHandlers() {},
    requestWindowCommandClose() {
      return true;
    },
    shouldCloseWindowFromInput,
    applyWindowOpacityToWindow() {},
    closeSettingsWindow() {},
    hideSettingsWindow() {},
  });

  await api.createWindow(
    {
      BrowserWindow: BrowserWindowStub,
      nativeTheme: {},
      app: {},
      screen: {},
      shell: {},
      ipcMain: {},
    },
    {
      preload: "/tmp/preload.cjs",
      devServerUrl: "http://localhost:5173",
      isDev: true,
      appIcon: null,
      isMac: false,
      electronDir: __dirname,
    },
  );

  let prevented = false;
  beforeInputHandler({ preventDefault: () => { prevented = true; } }, {
    type: "keyDown",
    control: true,
    shift: true,
    key: "R",
  });

  assert.equal(prevented, false);
  assert.deepEqual(ignoreMenuShortcutValues, [false]);
});

test("createWindow registers each main window as an independent app window", async () => {
  const registered = [];
  const unregistered = [];

  class BrowserWindowStub {
    constructor() {
      this.webContents = {
        id: registered.length + 1,
        on() {},
        once() {},
        isDestroyed() {
          return false;
        },
        isCrashed() {
          return false;
        },
        setIgnoreMenuShortcuts() {},
        setWindowOpenHandler() {},
        openDevTools() {},
      };
    }

    on(channel, handler) {
      if (channel === "closed") this._closedHandler = handler;
    }
    once() {}
    isDestroyed() { return false; }
    isMaximized() { return false; }
    isFullScreen() { return false; }
    getBounds() { return { x: 0, y: 0, width: 1400, height: 900 }; }
    setBackgroundColor() {}
    setOpacity() {}
    async loadURL() {}
    close() {
      this._closedHandler?.();
    }
  }

  const api = createMainWindowApi({
    mainWindow: null,
    electronApp: null,
    currentTheme: "light",
    isQuitting: false,
    pendingWindowStateWrite: null,
    queuedWindowState: null,
    windowStateCloseRequested: false,
    DEFAULT_WINDOW_WIDTH: 1400,
    DEFAULT_WINDOW_HEIGHT: 900,
    MIN_WINDOW_WIDTH: 1100,
    MIN_WINDOW_HEIGHT: 640,
    V8_CACHE_OPTIONS: "bypassHeatCheck",
    THEME_COLORS: { light: { background: "#fff" } },
    unhealthyWebContentsIds: new Set(),
    rendererReadySeenByWebContentsId: new Set(),
    __dirname,
    URL,
    require,
    console,
    setTimeout,
    clearTimeout,
    getGlobalShortcutBridge() {
      return { handleWindowClose: () => false };
    },
    debugLog() {},
    resolveFrontendBackgroundColor() { return null; },
    loadWindowState() { return null; },
    getDevRendererBaseUrl(url) { return url; },
    getWindowBoundsState() { return null; },
    queueWindowStateSave() {},
    saveWindowStateSync() {},
    setupDeferredShow() {},
    createExternalOnlyWindowOpenHandler() { return {}; },
    createAppWindowOpenHandler() { return {}; },
    attachOAuthLoadingOverlay() {},
    registerWindowHandlers() {},
    requestWindowCommandClose() {
      return true;
    },
    shouldCloseWindowFromInput,
    registerMainWindow(win) {
      registered.push(win);
    },
    unregisterMainWindow(win) {
      unregistered.push(win);
    },
    applyWindowOpacityToWindow() {},
    closeSettingsWindow() {},
    hideSettingsWindow() {},
  });

  const electronModule = {
    BrowserWindow: BrowserWindowStub,
    nativeTheme: {},
    app: {},
    screen: {},
    shell: {},
    ipcMain: {},
  };
  const options = {
    preload: "/tmp/preload.cjs",
    devServerUrl: "http://localhost:5173",
    isDev: true,
    appIcon: null,
    isMac: true,
    electronDir: __dirname,
  };

  const first = await api.createWindow(electronModule, options);
  const second = await api.createWindow(electronModule, options);

  assert.equal(registered.length, 2);
  assert.equal(registered[0], first);
  assert.equal(registered[1], second);
  assert.notEqual(first, second);

  first.close();
  assert.deepEqual(unregistered, [first]);
});

test("each main window close saves its own state", async () => {
  const closeHandlers = [];
  const savedStates = [];

  class BrowserWindowStub {
    constructor() {
      this.webContents = {
        id: closeHandlers.length + 1,
        on() {},
        once() {},
        isDestroyed() {
          return false;
        },
        isCrashed() {
          return false;
        },
        setIgnoreMenuShortcuts() {},
        setWindowOpenHandler() {},
        openDevTools() {},
      };
    }

    on(channel, handler) {
      if (channel === "close") closeHandlers.push(handler);
    }
    once() {}
    isDestroyed() { return false; }
    isMaximized() { return false; }
    isFullScreen() { return false; }
    getBounds() { return { x: 0, y: 0, width: 1400, height: 900 }; }
    setBackgroundColor() {}
    setOpacity() {}
    async loadURL() {}
    close() {}
  }

  const api = createMainWindowApi({
    mainWindow: null,
    electronApp: null,
    currentTheme: "light",
    isQuitting: false,
    pendingWindowStateWrite: null,
    queuedWindowState: null,
    windowStateCloseRequested: false,
    DEFAULT_WINDOW_WIDTH: 1400,
    DEFAULT_WINDOW_HEIGHT: 900,
    MIN_WINDOW_WIDTH: 1100,
    MIN_WINDOW_HEIGHT: 640,
    V8_CACHE_OPTIONS: "bypassHeatCheck",
    THEME_COLORS: { light: { background: "#fff" } },
    unhealthyWebContentsIds: new Set(),
    rendererReadySeenByWebContentsId: new Set(),
    __dirname,
    URL,
    require,
    console,
    setTimeout,
    clearTimeout,
    getGlobalShortcutBridge() {
      return { handleWindowClose: () => false };
    },
    debugLog() {},
    resolveFrontendBackgroundColor() { return null; },
    loadWindowState() { return null; },
    getDevRendererBaseUrl(url) { return url; },
    getWindowBoundsState(win) {
      return { windowId: win.webContents.id };
    },
    queueWindowStateSave() {},
    saveWindowStateSync(state) {
      savedStates.push(state);
    },
    setupDeferredShow() {},
    createExternalOnlyWindowOpenHandler() { return {}; },
    createAppWindowOpenHandler() { return {}; },
    attachOAuthLoadingOverlay() {},
    registerWindowHandlers() {},
    requestWindowCommandClose() {
      return true;
    },
    shouldCloseWindowFromInput,
    registerMainWindow() {},
    unregisterMainWindow() {},
    applyWindowOpacityToWindow() {},
    closeSettingsWindow() {},
    hideSettingsWindow() {},
  });

  const electronModule = {
    BrowserWindow: BrowserWindowStub,
    nativeTheme: {},
    app: {},
    screen: {},
    shell: {},
    ipcMain: {},
  };
  const options = {
    preload: "/tmp/preload.cjs",
    devServerUrl: "http://localhost:5173",
    isDev: true,
    appIcon: null,
    isMac: true,
    electronDir: __dirname,
  };

  await api.createWindow(electronModule, options);
  await api.createWindow(electronModule, options);

  assert.equal(closeHandlers.length, 2);
  closeHandlers[0]({});
  closeHandlers[1]({});

  assert.deepEqual(savedStates, [{ windowId: 1 }, { windowId: 2 }]);
});

test("window IPC handlers target the sender owner window", async () => {
  const handlers = new Map();
  const ipcMain = {
    handle(channel, handler) {
      handlers.set(channel, handler);
    },
    on(channel, handler) {
      handlers.set(channel, handler);
    },
  };
  const calls = [];
  const titles = [];
  const win = {
    isDestroyed() {
      return false;
    },
    setTitle(title) {
      titles.push(title);
    },
    focus() {
      calls.push("focus");
    },
    webContents: {
      id: 101,
      isDestroyed() {
        return false;
      },
      focus() {
        calls.push("webContents.focus");
      },
    },
  };

  registerWindowHandlers(ipcMain, { themeSource: "light" });

  const result = await handlers.get("netcatty:window:focus")({
    sender: {
      id: 202,
      getOwnerBrowserWindow() {
        return win;
      },
    },
  });

  assert.equal(result, true);
  assert.deepEqual(calls, ["focus", "webContents.focus"]);
  const titleResult = await handlers.get("netcatty:window:setTitle")({
    sender: {
      id: 202,
      getOwnerBrowserWindow() {
        return win;
      },
    },
  }, "Prod SSH");

  assert.equal(titleResult, true);
  assert.deepEqual(titles, ["Prod SSH"]);

  const opacityCalls = [];
  registerMainWindow({
    isDestroyed() {
      return false;
    },
    setOpacity(value) {
      opacityCalls.push(value);
    },
    webContents: {
      id: 303,
      isDestroyed() {
        return false;
      },
    },
  });

  const opacityResult = await handlers.get("netcatty:setWindowOpacity")(null, 0.7);
  assert.equal(opacityResult, true);
  assert.deepEqual(opacityCalls, [0.7]);
});

test("resolveSettingsWindowBounds centers settings on the requesting window display", () => {
  const sourceWindow = {
    getBounds() {
      return { x: 2100, y: 80, width: 900, height: 700 };
    },
    isDestroyed() {
      return false;
    },
  };
  const electronModule = {
    screen: {
      getDisplayMatching(bounds) {
        assert.deepEqual(bounds, { x: 2100, y: 80, width: 900, height: 700 });
        return { workArea: { x: 1920, y: 0, width: 1440, height: 900 } };
      },
    },
  };

  assert.deepEqual(
    resolveSettingsWindowBounds(electronModule, {
      sourceWindow,
      settingsWidth: 980,
      settingsHeight: 720,
    }),
    { x: 2150, y: 90 },
  );
});

function createSendableWindowStub({ destroyed = false, webContentsDestroyed = false } = {}) {
  const sent = [];
  return {
    sent,
    win: {
      isDestroyed() {
        return destroyed;
      },
      webContents: {
        id: 7,
        isDestroyed() {
          return webContentsDestroyed;
        },
        send(channel, payload) {
          sent.push({ channel, payload });
        },
      },
    },
  };
}

test("sendWhenRendererReady delivers the payload once the renderer reports ready", async () => {
  const { win, sent } = createSendableWindowStub();
  const waited = [];

  const result = await sendWhenRendererReady(
    win,
    "netcatty:window:openSession",
    { title: "Prod" },
    {
      timeoutMs: 8000,
      waitForReady: async (target, opts) => {
        waited.push({ target, opts });
      },
    },
  );

  assert.deepEqual(result, { success: true });
  assert.equal(waited.length, 1);
  assert.equal(waited[0].target, win);
  assert.deepEqual(waited[0].opts, { timeoutMs: 8000 });
  assert.deepEqual(sent, [
    { channel: "netcatty:window:openSession", payload: { title: "Prod" } },
  ]);
});

test("sendWhenRendererReady reports failure without sending when readiness times out", async () => {
  const { win, sent } = createSendableWindowStub();

  const result = await sendWhenRendererReady(
    win,
    "netcatty:window:openSession",
    { title: "Prod" },
    {
      timeoutMs: 5,
      waitForReady: async () => {
        throw new Error("Renderer did not report ready before timeout.");
      },
    },
  );

  assert.equal(result.success, false);
  assert.equal(sent.length, 0);
});

test("sendWhenRendererReady reports failure without sending when the window is gone after readiness", async () => {
  const { win, sent } = createSendableWindowStub({ destroyed: true });

  const result = await sendWhenRendererReady(
    win,
    "netcatty:window:openSession",
    { title: "Prod" },
    {
      timeoutMs: 8000,
      waitForReady: async () => {},
    },
  );

  assert.equal(result.success, false);
  assert.equal(sent.length, 0);
});
