import { describe, expect, it, mock } from "bun:test";
import { getSubscriptionKey as getLiveSubscriptionKey } from "@islandflow/types";

const redirect = mock((path: string) => {
  throw new Error(`NEXT_REDIRECT:${path}`);
});

const nextNavigationMock = {
  default: {
    redirect,
    usePathname: () => "/options"
  },
  redirect,
  usePathname: () => "/options"
};

const nextNavigationResolved = import.meta.resolve("next/navigation");
const nextNavigationJsResolved = import.meta.resolve("next/navigation.js");

mock.module("next/navigation", () => ({
  ...nextNavigationMock
}));
mock.module("next/navigation.js", () => ({
  ...nextNavigationMock
}));
mock.module(nextNavigationResolved, () => ({
  ...nextNavigationMock
}));
mock.module(nextNavigationJsResolved, () => ({
  ...nextNavigationMock
}));

const {
  NAV_ITEMS,
  appendHistoryTail,
  buildAlertContextPath,
  buildDefaultFlowFilters,
  buildOptionTapeQueryParams,
  classifierToneForFamily,
  collectAlertContextEvidence,
  composeTapeItems,
  deriveAlertDirection,
  countActiveFlowFilterGroups,
  decodeNewsText,
  filterOptionTapeItems,
  findAnchorRestoreIndex,
  formatCompactUsd,
  formatOptionContractLabel,
  flushPausableTapeData,
  getEffectiveOptionPrintFilters,
  getAlertWindowAnchorTs,
  getHotChannelFeedStatus,
  getLiveHistoryRetentionCap,
  getOptionTableSnapshot,
  getOptionScope,
  getLiveFeedStatus,
  getLiveManifest,
  getTerminalNavCurrentHref,
  getRouteFeatures,
  getTapeVirtualConfig,
  mergeHeldTapeHistory,
  mergeNewestWithOverflow,
  normalizeAlertSeverity,
  normalizeTickerFilterInput,
  nextFlowFilterPopoverState,
  isSyntheticAdminVisible,
  parseTickerFilterInput,
  prunePinnedEntries,
  projectPausableTapeState,
  reducePausableTapeData,
  shouldRetainLiveSnapshotHistory,
  shouldIncludeEquitiesForDarkUnderlyingFallback,
  shouldShowEquitiesSilentFeedWarning,
  selectPrimaryClassifierHit,
  shouldClearOptionFocusSeed,
  smartMoneyProfileLabel,
  smartMoneyToneForProfile,
  getAlertFlowPacketRefs,
  normalizeTerminalPathname,
  resolveAlertFlowPacket,
  statusLabel,
  toggleFilterValue
} = await import("./terminal");

const makeItem = (traceId: string, seq: number, ts: number) => ({
  trace_id: traceId,
  seq,
  ts
});

const makeOptionPrint = (overrides: Record<string, unknown> = {}) =>
  ({
    trace_id: "opt-1",
    seq: 1,
    ts: 1_000,
    source_ts: 1_000,
    ingest_ts: 1_001,
    option_contract_id: "AAPL-2025-01-17-200-C",
    underlying_id: "AAPL",
    option_type: "call",
    nbbo_side: "A",
    notional: 250_000,
    signal_pass: true,
    price: 1,
    size: 10,
    exchange: "X",
    ...overrides
  }) as any;

const makeAlert = (overrides: Record<string, unknown> = {}) =>
  ({
    trace_id: "alert-1",
    seq: 1,
    source_ts: 1_000,
    severity: "low",
    score: 20,
    hits: [],
    ...overrides
  }) as any;

describe("pinned evidence pruning", () => {
  it("returns the existing map when no entries need pruning", () => {
    const now = 50_000;
    const current = new Map([
      ["flowpacket:1", { value: { id: "flowpacket:1" }, updatedAt: now - 500 }],
      ["trace:2", { value: { id: "trace:2" }, updatedAt: now - 1_000 }]
    ]);

    const next = prunePinnedEntries(current, new Set(), now);

    expect(next).toBe(current);
  });
});

describe("alert context hydration helpers", () => {
  it("builds the persisted ClickHouse context endpoint path", () => {
    expect(buildAlertContextPath("alert:large_call/one")).toBe(
      "/flow/alerts/alert%3Alarge_call%2Fone/context"
    );
  });

  it("merges hydrated packets and prints into pinned evidence maps", () => {
    const packet = {
      trace_id: "flowpacket:1",
      id: "flowpacket:1",
      members: ["print:1"],
      source_ts: 1,
      ingest_ts: 2,
      seq: 1,
      features: {},
      join_quality: {}
    } as any;
    const print = makeOptionPrint({
      trace_id: "print:1",
      execution_nbbo_bid: 1.2,
      execution_nbbo_ask: 1.3,
      execution_underlying_spot: 450.05
    });

    const evidence = collectAlertContextEvidence({
      alert: makeAlert({ evidence_refs: ["flowpacket:1", "print:1"] }),
      flow_packets: [packet],
      option_prints: [print],
      missing_refs: []
    });

    expect(evidence.packets.get("flowpacket:1")).toBe(packet);
    expect(evidence.prints.get("print:1")?.execution_nbbo_bid).toBe(1.2);
    expect(evidence.prints.get("print:1")?.execution_underlying_spot).toBe(450.05);
  });

  it("finds flow-packet refs even when they are not first in alert evidence", () => {
    const alert = makeAlert({
      evidence_refs: ["smartmoney:single_leg_event:flowpacket:1", "flowpacket:1", "print:1"]
    });

    expect(getAlertFlowPacketRefs(alert)).toEqual(["flowpacket:1"]);
  });

  it("resolves the primary alert flow packet from hydrated historical context", () => {
    const packet = {
      trace_id: "flowpacket:1",
      id: "flowpacket:1",
      members: ["print:1"],
      source_ts: 1,
      ingest_ts: 2,
      seq: 1,
      features: {},
      join_quality: {}
    } as any;
    const alert = makeAlert({
      evidence_refs: ["smartmoney:single_leg_event:flowpacket:1", "flowpacket:1", "print:1"]
    });
    const packets = new Map<string, typeof packet>([[packet.id, packet]]);

    expect(resolveAlertFlowPacket(alert, packets)).toBe(packet);
  });
});

describe("live manifest", () => {
  it("includes only options channels on /options", () => {
    const filters = buildDefaultFlowFilters();
    const channels = getLiveManifest("/options", "SPY", 60000, filters).map(
      (subscription) => subscription.channel
    );

    expect(channels).toEqual(["options", "nbbo", "flow"]);
  });

  it("keeps /tape as a compatibility alias for /options subscriptions", () => {
    expect(getLiveManifest("/tape", "SPY", 60000, buildDefaultFlowFilters())).toEqual(
      getLiveManifest("/options", "SPY", 60000, buildDefaultFlowFilters())
    );
  });

  it("dedupes options subscriptions on /options", () => {
    const tapeOptionsSubscriptions = getLiveManifest(
      "/options",
      "SPY",
      60000,
      buildDefaultFlowFilters()
    ).filter((subscription) => subscription.channel === "options");
    expect(tapeOptionsSubscriptions).toHaveLength(1);
  });

  it("keeps option filters on /options subscriptions", () => {
    const filters = {
      ...buildDefaultFlowFilters(),
      minNotional: 125_000
    };

    const tapeOptionsSubscription = getLiveManifest("/options", "SPY", 60000, filters).find(
      (subscription) => subscription.channel === "options"
    );

    expect(tapeOptionsSubscription?.filters).toBe(filters);
  });

  it("applies global flow filters to flow subscriptions on /options", () => {
    const filters = {
      ...buildDefaultFlowFilters(),
      minNotional: 50_000
    };

    const tapeFlowSubscription = getLiveManifest("/options", "SPY", 60000, filters).find(
      (subscription) => subscription.channel === "flow"
    );

    expect(tapeFlowSubscription?.filters).toBe(filters);
  });

  it("includes scoped option subscriptions on /options", () => {
    const manifest = getLiveManifest(
      "/options",
      "AAPL",
      60000,
      buildDefaultFlowFilters(),
      {
        underlying_ids: ["AAPL"],
        option_contract_id: "AAPL-2025-01-17-200-C"
      },
      { underlying_ids: ["AAPL"] }
    );
    const optionsSubscription = manifest.find(
      (subscription): subscription is Extract<(typeof manifest)[number], { channel: "options" }> =>
        subscription.channel === "options"
    );

    expect(optionsSubscription?.underlying_ids).toEqual(["AAPL"]);
    expect(optionsSubscription?.option_contract_id).toBe("AAPL-2025-01-17-200-C");
    expect(optionsSubscription?.snapshot_limit).toBe(100);
    expect(manifest.some((subscription) => subscription.channel === "equities")).toBe(false);
  });

  it("drops option-print filters for contract-focused options subscriptions but keeps flow filters", () => {
    const filters = {
      ...buildDefaultFlowFilters(),
      minNotional: 500_000,
      optionTypes: ["put" as const]
    };
    const manifest = getLiveManifest(
      "/options",
      "AAPL",
      60000,
      filters,
      {
        underlying_ids: ["AAPL"],
        option_contract_id: "AAPL-2025-01-17-200-C"
      },
      { underlying_ids: ["AAPL"] },
      undefined
    );
    const optionsSubscription = manifest.find((subscription) => subscription.channel === "options");
    const flowSubscription = manifest.find((subscription) => subscription.channel === "flow");

    expect(optionsSubscription?.filters).toBeUndefined();
    expect(flowSubscription?.filters).toBe(filters);
  });

  it("scopes /signals subscriptions to signals channels only", () => {
    const channels = getLiveManifest("/signals", "SPY", 60000, buildDefaultFlowFilters()).map(
      (subscription) => subscription.channel
    );

    expect(channels).toEqual([
      "alerts",
      "smart-money",
      "classifier-hits",
      "inferred-dark",
      "equity-joins"
    ]);
  });

  it("includes news subscriptions on home and /news", () => {
    expect(
      getLiveManifest("/", "SPY", 60000, buildDefaultFlowFilters()).map(
        (subscription) => subscription.channel
      )
    ).toContain("news");
    expect(
      getLiveManifest("/news", "SPY", 60000, buildDefaultFlowFilters()).map(
        (subscription) => subscription.channel
      )
    ).toEqual(["news"]);
  });

  it("scopes /charts subscriptions to chart channels only", () => {
    const channels = getLiveManifest("/charts", "SPY", 60000, buildDefaultFlowFilters()).map(
      (subscription) => subscription.channel
    );

    expect(channels).toEqual([
      "smart-money",
      "inferred-dark",
      "equity-joins",
      "equity-candles",
      "equity-overlay"
    ]);
  });
});

describe("contract-focused option helpers", () => {
  it("uses the focused contract underlying for option scope even when ticker input differs", () => {
    expect(
      getOptionScope(["MSFT"], "AAPL", {
        kind: "option-contract",
        contractId: "AAPL-2025-01-17-200-C",
        underlyingId: "AAPL"
      })
    ).toEqual({
      underlying_ids: ["AAPL"],
      option_contract_id: "AAPL-2025-01-17-200-C"
    });
  });

  it("ignores broad flow filters for focused contract options", () => {
    const filters = {
      ...buildDefaultFlowFilters(),
      minNotional: 500_000
    };
    const items = [
      makeOptionPrint({
        trace_id: "focused-low",
        option_contract_id: "AAPL-2025-01-17-200-C",
        notional: 100_000,
        signal_pass: false
      }),
      makeOptionPrint({
        trace_id: "focused-high",
        seq: 2,
        ts: 2_000,
        option_contract_id: "AAPL-2025-01-17-200-C",
        notional: 750_000
      }),
      makeOptionPrint({
        trace_id: "other-contract",
        seq: 3,
        ts: 3_000,
        option_contract_id: "MSFT-2025-01-17-300-C",
        underlying_id: "MSFT",
        notional: 900_000
      })
    ];

    expect(
      filterOptionTapeItems(
        items,
        getEffectiveOptionPrintFilters(filters, true),
        {
          kind: "option-contract",
          contractId: "AAPL-2025-01-17-200-C",
          underlyingId: "AAPL"
        },
        new Set(["MSFT"]),
        "AAPL"
      ).map((item) => item.trace_id)
    ).toEqual(["focused-low", "focused-high"]);
  });

  it("includes option_contract_id and drops broad filters in focused replay query params", () => {
    const filters = {
      ...buildDefaultFlowFilters(),
      minNotional: 500_000,
      optionTypes: ["put" as const]
    };

    expect(
      buildOptionTapeQueryParams(getEffectiveOptionPrintFilters(filters, true), {
        underlying_ids: ["AAPL"],
        option_contract_id: "AAPL-2025-01-17-200-C"
      })
    ).toEqual({
      underlying_ids: "AAPL",
      option_contract_id: "AAPL-2025-01-17-200-C"
    });
  });

  it("includes the selected options view in tape query params", () => {
    expect(
      buildOptionTapeQueryParams(
        {
          ...buildDefaultFlowFilters(),
          view: "raw",
          securityTypes: undefined,
          nbboSides: undefined,
          optionTypes: undefined
        },
        { underlying_ids: ["AAPL"] }
      )
    ).toEqual({
      view: "raw",
      underlying_ids: "AAPL"
    });
  });

  it("keeps the focus seed until the matching scoped subscription has loaded it", () => {
    const seedItem = makeOptionPrint({
      trace_id: "focused-seed",
      option_contract_id: "AAPL-2025-01-17-200-C"
    });
    const seed = {
      scopeKey: "option-contract:AAPL-2025-01-17-200-C",
      subscriptionKey: getLiveSubscriptionKey({
        channel: "options",
        underlying_ids: ["AAPL"],
        option_contract_id: "AAPL-2025-01-17-200-C"
      }),
      items: [seedItem]
    };

    expect(
      shouldClearOptionFocusSeed(
        seed,
        "option-contract:AAPL-2025-01-17-200-C",
        getLiveSubscriptionKey({
          channel: "options",
          filters: {
            ...buildDefaultFlowFilters(),
            minNotional: 500_000
          },
          underlying_ids: ["AAPL"]
        }),
        [makeOptionPrint({ trace_id: "broad-old" })],
        []
      )
    ).toBe(false);

    expect(
      shouldClearOptionFocusSeed(
        seed,
        "option-contract:AAPL-2025-01-17-200-C",
        getLiveSubscriptionKey({
          channel: "options",
          underlying_ids: ["AAPL"],
          option_contract_id: "AAPL-2025-01-17-200-C"
        }),
        [seedItem],
        []
      )
    ).toBe(true);
  });
});

describe("route feature map", () => {
  it("maps /options to the options and packets panes", () => {
    const features = getRouteFeatures("/options");
    expect(features.showOptionsPane).toBe(true);
    expect(features.showEquitiesPane).toBe(false);
    expect(features.showFlowPane).toBe(true);
    expect(features.needsClassifierDecor).toBe(true);
    expect(features.alerts).toBe(false);
  });

  it("keeps /tape route compatibility while normalizing to /options", () => {
    expect(normalizeTerminalPathname("/tape")).toBe("/options");
    expect(getTerminalNavCurrentHref("/tape")).toBe("/options");
    expect(getRouteFeatures("/tape")).toEqual(getRouteFeatures("/options"));
  });

  it("maps /signals to signal panes and dependencies", () => {
    const features = getRouteFeatures("/signals");
    expect(features.showAlertsPane).toBe(true);
    expect(features.showClassifierPane).toBe(true);
    expect(features.showDarkPane).toBe(true);
    expect(features.options).toBe(false);
    expect(features.equityJoins).toBe(true);
  });

  it("maps /charts to chart panes and dependencies", () => {
    const features = getRouteFeatures("/charts");
    expect(features.showChartPane).toBe(true);
    expect(features.showFocusPane).toBe(true);
    expect(features.equityCandles).toBe(true);
    expect(features.equityOverlay).toBe(true);
    expect(features.alerts).toBe(false);
  });

  it("maps /news to the dedicated news pane", () => {
    const features = getRouteFeatures("/news");
    expect(features.news).toBe(true);
    expect(features.showNewsPane).toBe(true);
    expect(features.showAlertsPane).toBe(false);
  });
});

describe("fixed tape virtualization config", () => {
  it("uses expected fixed row heights and overscan by table", () => {
    expect(getTapeVirtualConfig("options")).toEqual({
      rowHeight: 36,
      overscan: 44,
      debugLabel: "options"
    });
    expect(getTapeVirtualConfig("equities")).toEqual({
      rowHeight: 36,
      overscan: 36,
      debugLabel: "equities"
    });
    expect(getTapeVirtualConfig("flow")).toEqual({
      rowHeight: 44,
      overscan: 24,
      debugLabel: "flow"
    });
    expect(getTapeVirtualConfig("alerts")).toEqual({
      rowHeight: 44,
      overscan: 24,
      debugLabel: "alerts"
    });
    expect(getTapeVirtualConfig("classifier")).toEqual({
      rowHeight: 44,
      overscan: 24,
      debugLabel: "classifier"
    });
    expect(getTapeVirtualConfig("dark")).toEqual({
      rowHeight: 44,
      overscan: 24,
      debugLabel: "dark"
    });
    expect(getTapeVirtualConfig("news")).toEqual({
      rowHeight: 52,
      overscan: 28,
      debugLabel: "news"
    });
  });
});

describe("news text formatting", () => {
  it("decodes common html entities in provider text", () => {
    expect(
      decodeNewsText(
        "Palantir CEO Alex Karp Is &#39;Rooting For Elon&#39; &amp; Clients &#x27;Screaming&#x27;"
      )
    ).toBe("Palantir CEO Alex Karp Is 'Rooting For Elon' & Clients 'Screaming'");
  });

  it("leaves unknown entities untouched", () => {
    expect(decodeNewsText("Keep &market; literal")).toBe("Keep &market; literal");
  });
});

describe("dark underlying route dependency helper", () => {
  it("does not keep extra equities subscriptions when joins+trace fallback are sufficient", () => {
    expect(shouldIncludeEquitiesForDarkUnderlyingFallback()).toBe(false);
    expect(
      getLiveManifest("/signals", "SPY", 60000, buildDefaultFlowFilters()).some(
        (subscription) => subscription.channel === "equities"
      )
    ).toBe(false);
    expect(
      getLiveManifest("/charts", "SPY", 60000, buildDefaultFlowFilters()).some(
        (subscription) => subscription.channel === "equities"
      )
    ).toBe(false);
  });
});

describe("terminal navigation", () => {
  it("exposes Dashboard, Options, and News as top-level destinations", () => {
    expect(NAV_ITEMS).toEqual([
      { href: "/", label: "Dashboard" },
      { href: "/options", label: "Options" },
      { href: "/news", label: "News" }
    ]);
  });
});

describe("synthetic admin visibility", () => {
  it("shows the internal control rail only when the public admin flag is enabled", () => {
    expect(isSyntheticAdminVisible("1")).toBe(true);
    expect(isSyntheticAdminVisible("0")).toBe(false);
    expect(isSyntheticAdminVisible(undefined)).toBe(false);
  });
});

describe("ticker filter helpers", () => {
  it("normalizes pasted ticker input into a stable terminal format", () => {
    expect(normalizeTickerFilterInput(" spy，\n nvda\u0000 aapl ")).toBe(" SPY, NVDA AAPL ");
  });

  it("parses, uppercases, and deduplicates ticker tokens", () => {
    expect(parseTickerFilterInput("spy, nvda spy\nqqq")).toEqual(["SPY", "NVDA", "QQQ"]);
  });
});

describe("live tape pausable helpers", () => {
  it("queues new items while paused and flushes them on resume", () => {
    let state = reducePausableTapeData(
      { visible: [], queued: [], seenKeys: new Set<string>(), dropped: 0 },
      [makeItem("a", 1, 100), makeItem("b", 2, 200)],
      false
    );

    expect(state.visible.map((item) => item.trace_id)).toEqual(["b", "a"]);
    expect(state.dropped).toBe(0);

    state = reducePausableTapeData(state, [makeItem("c", 3, 300)], true);
    expect(state.visible.map((item) => item.trace_id)).toEqual(["b", "a"]);
    expect(state.queued.map((item) => item.trace_id)).toEqual(["c"]);
    expect(state.dropped).toBe(1);

    state = flushPausableTapeData(state);
    expect(state.visible.map((item) => item.trace_id)).toEqual(["c", "b", "a"]);
    expect(state.queued).toHaveLength(0);
    expect(state.dropped).toBe(0);
  });

  it("does not duplicate unchanged arrays", () => {
    let state = reducePausableTapeData(
      { visible: [], queued: [], seenKeys: new Set<string>(), dropped: 0 },
      [makeItem("a", 1, 100)],
      false
    );

    state = reducePausableTapeData(state, [makeItem("a", 1, 100)], false);
    expect(state.visible.map((item) => item.trace_id)).toEqual(["a"]);
  });

  it("applies custom retention limits when requested", () => {
    const state = reducePausableTapeData(
      { visible: [], queued: [], seenKeys: new Set<string>(), dropped: 0 },
      [makeItem("a", 1, 100), makeItem("b", 2, 200), makeItem("c", 3, 300)],
      false,
      2
    );

    expect(state.visible.map((item) => item.trace_id)).toEqual(["c", "b"]);
    expect(state.visible).toHaveLength(2);
  });

  it("marks connected feeds stale once their freshest event ages past the threshold", () => {
    expect(getLiveFeedStatus("connected", 1000, 500, 1400)).toBe("connected");
    expect(getLiveFeedStatus("connected", 1000, 500, 1601)).toBe("stale");
    expect(getLiveFeedStatus("disconnected", 1000, 500, 1601)).toBe("disconnected");
  });

  it("waits for an additional behind-delay before surfacing stale", () => {
    expect(getLiveFeedStatus("connected", 1000, 500, 2000, 15_000)).toBe("connected");
    expect(getLiveFeedStatus("connected", 1000, 500, 16_501, 15_000)).toBe("stale");
  });

  it("keeps visible history even when live status is stale", () => {
    const projected = projectPausableTapeState([makeItem("stale", 7, 1000)], "stale", 2000);
    expect(projected.items.map((item) => item.trace_id)).toEqual(["stale"]);
    expect(projected.lastUpdate).toBeNull();
  });

  it("flags connected equities feeds that stay silent past threshold", () => {
    expect(
      shouldShowEquitiesSilentFeedWarning({
        wsStatus: "connected",
        equitiesSubscribed: true,
        connectedAt: 1_000,
        lastEquitiesEventAt: null,
        now: 20_000,
        thresholdMs: 25_000
      })
    ).toBe(false);

    expect(
      shouldShowEquitiesSilentFeedWarning({
        wsStatus: "connected",
        equitiesSubscribed: true,
        connectedAt: 1_000,
        lastEquitiesEventAt: null,
        now: 27_000,
        thresholdMs: 25_000
      })
    ).toBe(true);

    expect(
      shouldShowEquitiesSilentFeedWarning({
        wsStatus: "connected",
        equitiesSubscribed: true,
        connectedAt: 1_000,
        lastEquitiesEventAt: 20_000,
        now: 40_000,
        thresholdMs: 25_000
      })
    ).toBe(false);
  });

  it("retains live history when freshness-gated snapshots are empty", () => {
    expect(shouldRetainLiveSnapshotHistory("options", true, 0, 3)).toBe(true);
    expect(shouldRetainLiveSnapshotHistory("equities", true, 0, 2)).toBe(true);
    expect(shouldRetainLiveSnapshotHistory("alerts", true, 0, 3)).toBe(false);
    expect(shouldRetainLiveSnapshotHistory("options", true, 1, 3)).toBe(false);
    expect(shouldRetainLiveSnapshotHistory("options", false, 0, 3)).toBe(false);
  });
});

describe("live tape history helpers", () => {
  it("composes tape items across seed, live, and history without seam duplicates", () => {
    const seed = [makeItem("seed", 1, 100), makeItem("dup", 2, 200)];
    const live = [makeItem("live", 5, 500), makeItem("dup", 2, 200)];
    const history = [makeItem("old", 0, 50), makeItem("mid", 3, 300)];

    expect(composeTapeItems(seed, live, history).map((item) => item.trace_id)).toEqual([
      "live",
      "mid",
      "dup",
      "seed",
      "old"
    ]);
  });

  it("keeps a clicked seed row visible before scoped live and history arrive", () => {
    const clicked = makeItem("clicked", 3, 300);

    expect(composeTapeItems([clicked], [], []).map((item) => item.trace_id)).toEqual(["clicked"]);
  });

  it("drops focus seed duplicates once equivalent live or history rows arrive", () => {
    const clicked = makeItem("clicked", 3, 300);
    const live = [makeItem("new", 4, 400)];
    const history = [makeItem("clicked", 3, 300)];

    expect(composeTapeItems([clicked], live, history).map((item) => item.trace_id)).toEqual([
      "new",
      "clicked"
    ]);
  });

  it("promotes hot-window overflow into the history tail", () => {
    const currentHot = [
      makeItem("hot-3", 3, 300),
      makeItem("hot-2", 2, 200),
      makeItem("hot-1", 1, 100)
    ];
    const incoming = [makeItem("hot-4", 4, 400)];

    const { kept, evicted } = mergeNewestWithOverflow(incoming, currentHot, 3);
    const nextHistory = appendHistoryTail([], evicted, kept, 5000);

    expect(kept.map((item) => item.trace_id)).toEqual(["hot-4", "hot-3", "hot-2"]);
    expect(nextHistory.map((item) => item.trace_id)).toEqual(["hot-1"]);
  });

  it("keeps the combined tape continuous beyond the hot live window", () => {
    let hot: Array<ReturnType<typeof makeItem>> = [];
    let history: Array<ReturnType<typeof makeItem>> = [];

    for (let seq = 1; seq <= 5; seq += 1) {
      const { kept, evicted } = mergeNewestWithOverflow(
        [makeItem(`row-${seq}`, seq, seq * 100)],
        hot,
        2
      );
      hot = kept;
      history = appendHistoryTail(history, evicted, hot, 5000);
    }

    expect([...hot, ...history].map((item) => item.trace_id)).toEqual([
      "row-5",
      "row-4",
      "row-3",
      "row-2",
      "row-1"
    ]);
  });

  it("appends older scoped rows behind the hot live head", () => {
    const liveHead = Array.from({ length: 100 }, (_, idx) =>
      makeItem(`hot-${idx}`, 200 - idx, 2_000 - idx)
    );
    const older = [makeItem("older-1", 99, 999), makeItem("older-2", 98, 998)];

    const next = appendHistoryTail([], older, liveHead, 5000);

    expect(next.map((item) => item.trace_id)).toEqual(["older-1", "older-2"]);
  });

  it("skips duplicates already present in the live head", () => {
    const liveHead = [makeItem("latest", 3, 300), makeItem("duplicate", 2, 200)];
    const older = [makeItem("duplicate", 2, 200), makeItem("older", 1, 100)];

    const next = appendHistoryTail([], older, liveHead, 5000);

    expect(next.map((item) => item.trace_id)).toEqual(["older"]);
  });

  it("dedupes the seam between promoted overflow and fetched history", () => {
    const currentHot = [
      makeItem("hot-3", 3, 300),
      makeItem("hot-2", 2, 200),
      makeItem("hot-1", 1, 100)
    ];
    const { kept, evicted } = mergeNewestWithOverflow([makeItem("hot-4", 4, 400)], currentHot, 3);
    const promoted = appendHistoryTail([], evicted, kept, 5000);
    const merged = appendHistoryTail(
      promoted,
      [makeItem("hot-1", 1, 100), makeItem("older", 0, 50)],
      kept,
      5000
    );

    expect(merged.map((item) => item.trace_id)).toEqual(["hot-1", "older"]);
    expect(new Set([...kept, ...merged].map((item) => item.trace_id)).size).toBe(
      kept.length + merged.length
    );
  });

  it("trims the history tail to the soft cap", () => {
    const current = [makeItem("existing", 4, 400)];
    const older = [makeItem("older-1", 3, 300), makeItem("older-2", 2, 200)];

    const next = appendHistoryTail(current, older, [], 2);

    expect(next.map((item) => item.trace_id)).toEqual(["existing", "older-1"]);
  });

  it("keeps option and equity history effectively unbounded while scrolling", () => {
    expect(
      getLiveHistoryRetentionCap({
        channel: "options",
        underlying_ids: ["AAPL"],
        option_contract_id: "AAPL-2025-01-17-200-C"
      } as any)
    ).toBe(0);
    expect(
      getLiveHistoryRetentionCap({
        channel: "equities",
        underlying_ids: ["AAPL"]
      } as any)
    ).toBe(0);
  });

  it("restores the same anchor key after live insertions at the top", () => {
    const nextKeys = ["new-1", "new-2", "anchor", "after-1", "after-2"];
    expect(findAnchorRestoreIndex(nextKeys, "anchor", ["anchor", "after-1", "after-2"])).toBe(2);
  });

  it("falls forward to the nearest surviving key when the anchor is evicted", () => {
    const nextKeys = ["new-1", "after-1", "after-2"];
    expect(findAnchorRestoreIndex(nextKeys, "anchor", ["anchor", "after-1", "after-2"])).toBe(1);
  });

  it("keeps the same anchor when history is appended at the bottom", () => {
    const nextKeys = ["anchor", "after-1", "after-2", "older-1", "older-2"];
    expect(findAnchorRestoreIndex(nextKeys, "anchor", ["anchor", "after-1", "after-2"])).toBe(0);
  });

  it("keeps held ClickHouse history stable when newer live overflow arrives", () => {
    const frozenLive = [makeItem("hot-5", 5, 500), makeItem("hot-4", 4, 400)];
    const displayed = [makeItem("hist-3", 3, 300), makeItem("hist-2", 2, 200)];
    const incoming = [
      makeItem("overflow-newer", 6, 600),
      makeItem("hot-4", 4, 400),
      makeItem("hist-3", 3, 300),
      makeItem("hist-2", 2, 200)
    ];

    expect(
      mergeHeldTapeHistory(displayed, incoming, frozenLive).map((item) => item.trace_id)
    ).toEqual(["hist-3", "hist-2"]);
  });

  it("appends truly older lazy-loaded rows to the held history tail", () => {
    const frozenLive = [makeItem("hot-5", 5, 500), makeItem("hot-4", 4, 400)];
    const displayed = [makeItem("hist-3", 3, 300), makeItem("hist-2", 2, 200)];
    const incoming = [
      makeItem("hist-3", 3, 300),
      makeItem("hist-2", 2, 200),
      makeItem("older-1", 1, 100),
      makeItem("older-0", 0, 50)
    ];

    expect(
      mergeHeldTapeHistory(displayed, incoming, frozenLive).map((item) => item.trace_id)
    ).toEqual(["hist-3", "hist-2", "older-1", "older-0"]);
  });

  it("resyncs buffered live history by replacing the held segment after resume", () => {
    const frozenLive = [makeItem("hot-5", 5, 500), makeItem("hot-4", 4, 400)];
    const held = mergeHeldTapeHistory(
      [makeItem("hist-3", 3, 300), makeItem("hist-2", 2, 200)],
      [makeItem("overflow-newer", 6, 600), makeItem("hist-3", 3, 300), makeItem("older-1", 1, 100)],
      frozenLive
    );
    const resynced = appendHistoryTail([], [makeItem("overflow-newer", 6, 600), ...held], [], 0);

    expect(held.map((item) => item.trace_id)).toEqual(["hist-3", "hist-2", "older-1"]);
    expect(resynced.map((item) => item.trace_id)).toEqual([
      "overflow-newer",
      "hist-3",
      "hist-2",
      "older-1"
    ]);
  });
});

describe("options display formatters", () => {
  it("formats dashed option contracts as ticker strike expiry", () => {
    expect(formatOptionContractLabel("SPY-2025-01-17-450-C")).toEqual({
      ticker: "SPY",
      strike: "450C",
      expiration: "01-17-25"
    });
  });

  it("formats OCC contracts as ticker strike expiry", () => {
    expect(formatOptionContractLabel("AAPL250117P00150000")).toEqual({
      ticker: "AAPL",
      strike: "150P",
      expiration: "01-17-25"
    });
  });

  it("preserves decimal strikes and side suffix", () => {
    expect(formatOptionContractLabel("QQQ-2025-01-17-509.5-C")).toEqual({
      ticker: "QQQ",
      strike: "509.5C",
      expiration: "01-17-25"
    });
  });

  it("returns null when contract parsing fails", () => {
    expect(formatOptionContractLabel("not-a-contract")).toBeNull();
  });

  it("formats compact notional values", () => {
    expect(formatCompactUsd(999)).toBe("999.00");
    expect(formatCompactUsd(11_430)).toBe("11.4K");
    expect(formatCompactUsd(1_250_000)).toBe("1.3M");
    expect(formatCompactUsd(Number.NaN)).toBe("0.00");
  });

  it("renders options table snapshot values from preserved spot and IV", () => {
    expect(
      getOptionTableSnapshot({
        price: 1.25,
        size: 10,
        notional: 12_500,
        execution_nbbo_side: "A",
        execution_underlying_spot: 450.05,
        execution_iv: 0.42
      })
    ).toEqual({
      spot: "450.05",
      iv: "42%",
      side: "A",
      details: "10@1.25_A",
      value: "12.5K"
    });
  });

  it("renders legacy options table snapshot spot and IV as dashes", () => {
    const snapshot = getOptionTableSnapshot({
      price: 1,
      size: 2
    });

    expect(snapshot.spot).toBe("--");
    expect(snapshot.iv).toBe("--");
  });
});

describe("classifier row decoration helpers", () => {
  it("maps classifier families to row tones", () => {
    expect(classifierToneForFamily("large_bullish_call_sweep")).toBe("green");
    expect(classifierToneForFamily("large_bearish_put_sweep")).toBe("red");
    expect(classifierToneForFamily("straddle")).toBe("blue");
    expect(classifierToneForFamily("unknown_family")).toBe("neutral");
  });

  it("selects primary hits by confidence, source timestamp, then seq", () => {
    const hit = selectPrimaryClassifierHit([
      {
        ...makeAlert({ classifier_id: "old", confidence: 0.9, source_ts: 1_000, seq: 1 }),
        direction: "bullish",
        explanations: []
      },
      {
        ...makeAlert({ classifier_id: "new", confidence: 0.9, source_ts: 2_000, seq: 1 }),
        direction: "bullish",
        explanations: []
      },
      {
        ...makeAlert({ classifier_id: "low", confidence: 0.5, source_ts: 3_000, seq: 9 }),
        direction: "bullish",
        explanations: []
      }
    ]);

    expect(hit?.classifier_id).toBe("new");
  });
});

describe("smart-money profile helpers", () => {
  it("labels and colors primary profiles", () => {
    expect(smartMoneyProfileLabel("institutional_directional")).toBe("Institutional Directional");
    expect(smartMoneyProfileLabel(null)).toBe("Abstained");
    expect(smartMoneyToneForProfile("event_driven")).toBe("blue");
    expect(smartMoneyToneForProfile(null)).toBe("neutral");
  });
});

describe("flow filter popup helpers", () => {
  it("opens and closes the popup via toggle and dismiss actions", () => {
    expect(nextFlowFilterPopoverState(false, "toggle")).toBe(true);
    expect(nextFlowFilterPopoverState(true, "toggle")).toBe(false);
    expect(nextFlowFilterPopoverState(true, "dismiss")).toBe(false);
  });

  it("tracks active filter groups and resets to defaults", () => {
    const defaults = buildDefaultFlowFilters();
    const next = {
      ...defaults,
      securityTypes: toggleFilterValue(defaults.securityTypes, "etf", true),
      nbboSides: toggleFilterValue(defaults.nbboSides, "B", true),
      minNotional: 25_000
    };

    expect(countActiveFlowFilterGroups(defaults)).toBe(0);
    expect(countActiveFlowFilterGroups(next)).toBe(3);
    expect(countActiveFlowFilterGroups({ ...defaults, view: "raw" })).toBe(1);
    expect(buildDefaultFlowFilters()).toEqual(defaults);
  });
});

describe("signals helpers", () => {
  it("normalizes severity aliases/casing and falls back to score", () => {
    expect(normalizeAlertSeverity(makeAlert({ severity: "HIGH", score: 1 }))).toBe("high");
    expect(normalizeAlertSeverity(makeAlert({ severity: "med", score: 1 }))).toBe("medium");
    expect(normalizeAlertSeverity(makeAlert({ severity: "informational", score: 99 }))).toBe("low");
    expect(normalizeAlertSeverity(makeAlert({ severity: "unknown", score: 80 }))).toBe("high");
    expect(normalizeAlertSeverity(makeAlert({ severity: "unknown", score: 45 }))).toBe("medium");
    expect(normalizeAlertSeverity(makeAlert({ severity: "unknown", score: 44 }))).toBe("low");
  });

  it("derives dominant direction with confidence tie-break and neutral fallback", () => {
    expect(
      deriveAlertDirection(
        makeAlert({
          hits: [
            { direction: "bullish", confidence: 0.4 },
            { direction: "bullish", confidence: 0.2 },
            { direction: "bearish", confidence: 0.9 }
          ]
        })
      )
    ).toBe("bullish");

    expect(
      deriveAlertDirection(
        makeAlert({
          hits: [
            { direction: "bullish", confidence: 0.4 },
            { direction: "bearish", confidence: 0.9 }
          ]
        })
      )
    ).toBe("bearish");

    expect(
      deriveAlertDirection(makeAlert({ hits: [{ direction: "weird", confidence: 0.4 }] }))
    ).toBe("neutral");
    expect(deriveAlertDirection(makeAlert({ hits: [] }))).toBe("neutral");
  });

  it("anchors strip window to latest visible alert timestamp", () => {
    const alerts = [
      makeAlert({ source_ts: 1_700_000_000_000, severity: "high" }),
      makeAlert({ source_ts: 1_700_000_000_000 - 10 * 60 * 1000, severity: "low" })
    ];
    expect(getAlertWindowAnchorTs(alerts, 42)).toBe(1_700_000_000_000);
    expect(getAlertWindowAnchorTs([], 42)).toBe(42);
  });

  it("returns connected/held/stale live status labels without live wording", () => {
    expect(statusLabel("connected", false, "live")).toBe("Connected");
    expect(statusLabel("connected", true, "live")).toBe("Held");
    expect(statusLabel("stale", false, "live")).toBe("Feed behind");
    expect(statusLabel("stale", true, "live")).toBe("Feed behind");
  });

  it("keeps replay pause wording on replay tapes", () => {
    expect(statusLabel("connected", true, "replay")).toBe("Paused");
  });

  it("treats healthy scoped channels as connected even when no matching rows are visible", () => {
    expect(getHotChannelFeedStatus("connected", { healthy: true })).toBe("connected");
  });

  it("surfaces feed behind only when the backend channel health is stale", () => {
    expect(getHotChannelFeedStatus("connected", { healthy: false })).toBe("stale");
    expect(getHotChannelFeedStatus("disconnected", { healthy: true })).toBe("disconnected");
  });
});
