import test from "node:test";
import assert from "node:assert/strict";
import {
  computeLogsSignature,
  resolveInitialVisibility,
  shouldAutoRefresh,
} from "../../src/shared/components/requestLoggerSignature.ts";

const PAGE_SIZE = 50;

test("shouldAutoRefresh: polls only while recording AND on the first page", () => {
  assert.equal(shouldAutoRefresh(true, PAGE_SIZE, PAGE_SIZE), true); // exactly first page
  assert.equal(shouldAutoRefresh(true, 10, PAGE_SIZE), true);
  assert.equal(shouldAutoRefresh(false, 10, PAGE_SIZE), false); // not recording
  assert.equal(shouldAutoRefresh(true, PAGE_SIZE + 1, PAGE_SIZE), false); // scrolled past page 1
  assert.equal(shouldAutoRefresh(true, 500, PAGE_SIZE), false); // deep history window
});

test("computeLogsSignature: stable across identical snapshots", () => {
  const snapshot = [
    { id: "a", status: 200, duration: 12, tokens: { out: 5 } },
    { id: "b", status: 200, duration: 30, tokens: { out: 9 } },
  ];
  assert.equal(computeLogsSignature(snapshot), computeLogsSignature(structuredClone(snapshot)));
});

test("computeLogsSignature: changes when an in-progress request updates", () => {
  const before = [{ id: "a", status: 0, duration: 0, tokens: { out: 0 } }];
  const afterStatus = [{ id: "a", status: 200, duration: 0, tokens: { out: 0 } }];
  const afterDuration = [{ id: "a", status: 0, duration: 42, tokens: { out: 0 } }];
  const afterTokens = [{ id: "a", status: 0, duration: 0, tokens: { out: 7 } }];
  const base = computeLogsSignature(before);
  assert.notEqual(computeLogsSignature(afterStatus), base);
  assert.notEqual(computeLogsSignature(afterDuration), base);
  assert.notEqual(computeLogsSignature(afterTokens), base);
});

test("computeLogsSignature: detects additions and deletions", () => {
  const one = [{ id: "a", status: 200, duration: 1, tokens: { out: 1 } }];
  const two = [...one, { id: "b", status: 200, duration: 1, tokens: { out: 1 } }];
  assert.notEqual(computeLogsSignature(one), computeLogsSignature(two));
});

test("computeLogsSignature: non-array input collapses to empty", () => {
  assert.equal(computeLogsSignature(undefined), "");
  assert.equal(computeLogsSignature(null), "");
  assert.equal(computeLogsSignature({ error: "boom" }), "");
  assert.equal(computeLogsSignature([]), "");
});

test("computeLogsSignature: missing tokens defaults out to 0", () => {
  assert.equal(
    computeLogsSignature([{ id: "a", status: 200, duration: 5 }]),
    "a:200:5:0"
  );
});

test("resolveInitialVisibility: visible by default when document is absent (SSR)", () => {
  const original = (globalThis as any).document;
  try {
    delete (globalThis as any).document;
    assert.equal(resolveInitialVisibility(), true);
  } finally {
    if (original !== undefined) (globalThis as any).document = original;
  }
});

test("resolveInitialVisibility: mirrors document.visibilityState when present", () => {
  const original = (globalThis as any).document;
  try {
    (globalThis as any).document = { visibilityState: "hidden" };
    assert.equal(resolveInitialVisibility(), false);
    (globalThis as any).document = { visibilityState: "visible" };
    assert.equal(resolveInitialVisibility(), true);
  } finally {
    if (original === undefined) delete (globalThis as any).document;
    else (globalThis as any).document = original;
  }
});
