import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { test } from "bun:test";

const srcRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");

test("issue 853 persists submitted user and running agent messages before long Code Agent polling", () => {
  const source = fs.readFileSync(path.join(srcRoot, "state/workbench.ts"), "utf8");
  const visibleMessagesIndex = source.indexOf("const visibleMessages =", source.indexOf("const pendingWithRetry"));
  const pendingIndex = source.indexOf('dispatch({ type: "message:pending"');
  const persistIndex = source.indexOf("let currentWorkspace = await persistConversation", pendingIndex);
  const routeIndex = source.indexOf("const route = steerMode ? api.steerAgentMessage : api.sendAgentMessage", pendingIndex);
  assert.ok(visibleMessagesIndex > 0);
  assert.ok(pendingIndex > 0);
  assert.ok(persistIndex > pendingIndex);
  assert.ok(routeIndex > persistIndex);
  assert.match(source.slice(visibleMessagesIndex, persistIndex), /: \[\.\.\.state\.messages, user, pendingWithRetry\]/u);
  assert.match(source.slice(persistIndex, routeIndex), /messages: visibleMessages/u);
});

test("issue 853 submit failure persists the same trace before refresh", () => {
  const source = fs.readFileSync(path.join(srcRoot, "state/workbench.ts"), "utf8");
  const failureIndex = source.indexOf('const traceSnapshot = await fetchTraceSnapshot(traceId, traceId, Math.max(8000, state.codeAgentTimeoutMs), undefined, activeProjectId);');
  const keepSteerIndex = source.indexOf('const keepSteerActive = steerMode && response.status === 0', failureIndex);
  const steerDoneIndex = source.indexOf('dispatch({ type: "chat:steer-done" });', keepSteerIndex);
  const failedWithTraceIndex = source.indexOf('const failedWithTrace = runnerTrace ? { ...failed, runnerTrace } : failed;', failureIndex);
  const persistIndex = source.indexOf('messages: replaceMessage(visibleMessages, activePending.id, failedWithTrace)', failedWithTraceIndex);
  assert.ok(failureIndex > 0);
  assert.ok(keepSteerIndex > failureIndex);
  assert.ok(steerDoneIndex > keepSteerIndex);
  assert.ok(failedWithTraceIndex > failureIndex);
  assert.ok(persistIndex > failedWithTraceIndex);
});

test("issue 853 left sidebar collapse only removes the left columns", () => {
  const css = fs.readFileSync(path.join(srcRoot, "styles/workbench.css"), "utf8");
  assert.match(css, /--right-sidebar-left-collapsed-width: min\(var\(--right-sidebar-width\), 46vw\);/u);
  assert.match(css, /\.workbench-shell\.is-left-sidebar-collapsed \.workspace-body \{ grid-template-columns: 0 0 minmax\(360px, 1fr\) var\(--resize-handle-width\) minmax\(min\(var\(--right-sidebar-min-width\), 46vw\), var\(--right-sidebar-left-collapsed-width\)\); \}/u);
  assert.match(css, /\.center-workspace \{ grid-column: 3; \}/u);
  assert.match(css, /\.right-sidebar \{ grid-column: 5; \}/u);
  assert.match(css, /\.workspace-body\.is-route-without-sidebars \.center-workspace \{ grid-column: 1; \}/u);
  assert.doesNotMatch(css, /\.workbench-shell\.is-left-sidebar-collapsed \.workspace-body \{ grid-template-columns: 0 0 minmax\(0, 1fr\) var\(--resize-handle-width\) var\(--right-sidebar-width\); \}/u);
});

test("issue 853 completed trace panels only auto-collapse after a final response exists", () => {
  const source = fs.readFileSync(path.join(srcRoot, "components/conversation/MessageTracePanel.tsx"), "utf8");
  assert.match(source, /shouldCollapseForFinalResponse = collapseWhenFinalResponse === true && !traceRunning/u);
  assert.match(source, /if \(traceRunning\) \{\n\s+setOpen\(true\);\n\s+\}/u);
});
