import assert from "node:assert/strict";
import { test } from "bun:test";

import {
  classifyWorkbenchKafkaDebugReplayClientOverlay,
  classifyWorkbenchKafkaDebugReplayResult,
  completeWorkbenchKafkaDebugReplay,
  createWorkbenchKafkaDebugReplayTracker,
  markWorkbenchKafkaDebugReplayBarrierComplete,
  markWorkbenchKafkaDebugReplayConsumerReady,
  observeWorkbenchKafkaDebugReplayRecord,
  recordWorkbenchKafkaDebugReplayDelivery
} from "./workbench-kafka-debug-replay-contract.ts";

const readyConsumer = { ready: true, groupId: "hwlab-debug-test" };
const deliveredCounts = {
  scanned: 1,
  barrierScanned: 1,
  parsed: 1,
  traceMatched: 1,
  replayMatched: 1,
  matched: 1,
  delivered: 1,
  clientReceived: 1,
  decoded: 1,
  applied: 1
};

test("isolated replay classifies an empty producer result", () => {
  const result = classifyWorkbenchKafkaDebugReplayResult({
    replayId: "rpl_empty",
    traceId: "trc_empty",
    producer: { invoked: false, sourceMatched: null },
    consumer: readyConsumer,
    counts: {},
    terminalObserved: false
  });
  assert.deepEqual(result, {
    ok: false,
    phase: "producer",
    code: "producer_not_invoked",
    message: "No isolated debug producer was invoked for this replay."
  });
});

test("isolated replay classifies matching events without terminal", () => {
  const result = classifyWorkbenchKafkaDebugReplayResult({
    replayId: "rpl_no_terminal",
    traceId: "trc_no_terminal",
    producer: { invoked: true, sourceMatched: true },
    consumer: readyConsumer,
    counts: deliveredCounts,
    terminalObserved: false
  });
  assert.equal(result.code, "terminal_missing");
  assert.equal(result.phase, "terminal");
});

test("isolated replay classifies production reducer rejection", () => {
  const result = classifyWorkbenchKafkaDebugReplayResult({
    replayId: "rpl_reducer_rejected",
    traceId: "trc_reducer_rejected",
    producer: { invoked: true, sourceMatched: true },
    consumer: readyConsumer,
    counts: { ...deliveredCounts, applied: 0 },
    terminalObserved: true
  });
  assert.equal(result.code, "reducer_rejected");
  assert.equal(result.phase, "client");
});

test("isolated replay classifies terminal completion", () => {
  const result = classifyWorkbenchKafkaDebugReplayResult({
    replayId: "rpl_complete",
    traceId: "trc_complete",
    producer: { invoked: true, sourceMatched: true },
    consumer: readyConsumer,
    counts: deliveredCounts,
    terminalObserved: true
  });
  assert.deepEqual(result, {
    ok: true,
    phase: "terminal",
    code: "terminal_complete",
    message: "The isolated replay reached a terminal event."
  });
});

test("isolated replay keeps source, filter, and decoder failures distinct", () => {
  const sourceMissing = classifyWorkbenchKafkaDebugReplayResult({
    replayId: "rpl_source_missing",
    traceId: "trc_source_missing",
    producer: { invoked: true, sourceMatched: false },
    consumer: readyConsumer,
    counts: { scanned: 2, barrierScanned: 2, parsed: 2, traceMatched: 0 },
    terminalObserved: false
  });
  const filterMismatch = classifyWorkbenchKafkaDebugReplayResult({
    replayId: "rpl_filter_mismatch",
    traceId: "trc_filter_mismatch",
    producer: { invoked: true, sourceMatched: true },
    consumer: readyConsumer,
    counts: { scanned: 2, barrierScanned: 2, parsed: 2, traceMatched: 2, replayMatched: 0 },
    terminalObserved: false
  });
  const decoderRejected = classifyWorkbenchKafkaDebugReplayResult({
    replayId: "rpl_decoder_rejected",
    traceId: "trc_decoder_rejected",
    producer: { invoked: true, sourceMatched: true },
    consumer: readyConsumer,
    counts: { ...deliveredCounts, decoded: 0, applied: 0 },
    terminalObserved: true
  });
  assert.equal(sourceMissing.code, "source_trace_missing");
  assert.equal(filterMismatch.code, "records_scanned_but_filter_mismatch");
  assert.equal(decoderRejected.code, "decoder_rejected");
});

test("correlated replay requires seek, lastOffset, and complete unique batch cardinality", () => {
  const complete = correlatedReplay();
  assert.equal(classifyWorkbenchKafkaDebugReplayResult(complete).code, "terminal_complete");

  const seekMissing = correlatedReplay({ barrier: { seekApplied: false, completed: true, lastOffsetObserved: true } });
  assert.equal(classifyWorkbenchKafkaDebugReplayResult(seekMissing).code, "consumer_seek_not_applied");

  const lastOffsetMissing = correlatedReplay({ barrier: { seekApplied: true, completed: false, lastOffsetObserved: false } });
  assert.equal(classifyWorkbenchKafkaDebugReplayResult(lastOffsetMissing).code, "barrier_not_completed");

  const middleOffsetMissing = correlatedReplay({
    requestedOffsetRange: { partition: 0, firstOffset: "10", lastOffset: "12" },
    producer: { invoked: true, sourceMatched: true, publishedCount: 3 }
  });
  assert.equal(classifyWorkbenchKafkaDebugReplayResult(middleOffsetMissing).code, "barrier_cardinality_mismatch");

  const duplicateOffset = correlatedReplay({ rejectedByReason: { duplicate_offset: 1 } });
  assert.equal(classifyWorkbenchKafkaDebugReplayResult(duplicateOffset).code, "barrier_duplicate_offset");
});

test("correlated replay fails typed parse, filter, delivery, and producer evidence loss", () => {
  const parseLost = correlatedReplay({ counts: { ...correlatedCounts(), parsed: 1, traceMatched: 1, replayMatched: 1, matched: 1, delivered: 1 } });
  const filterLost = correlatedReplay({ counts: { ...correlatedCounts(), traceMatched: 1, replayMatched: 1, matched: 1, delivered: 1 } });
  const deliveryLost = correlatedReplay({ counts: { ...correlatedCounts(), delivered: 1 } });
  const producerFalse = correlatedReplay({ producer: { invoked: false, sourceMatched: true, publishedCount: 2 } });
  assert.equal(classifyWorkbenchKafkaDebugReplayResult(parseLost).code, "record_parse_rejected");
  assert.equal(classifyWorkbenchKafkaDebugReplayResult(filterLost).code, "records_scanned_but_filter_mismatch");
  assert.equal(classifyWorkbenchKafkaDebugReplayResult(deliveryLost).code, "sse_write_failed");
  assert.equal(classifyWorkbenchKafkaDebugReplayResult(producerFalse).code, "producer_not_invoked");
});

test("server result declares client counts unavailable and client overlay reuses the pure classifier", () => {
  const serverResult = {
    ...correlatedReplay(),
    offsetRange: { requested: { partition: 0, firstOffset: "10", lastOffset: "11" } },
    completionReason: "barrier",
    classificationScope: "server",
    requiresClientOverlay: true,
    clientCounts: { available: false, received: null, decoded: null, applied: null }
  };
  const overlay = classifyWorkbenchKafkaDebugReplayClientOverlay(serverResult, { received: 2, decoded: 2, applied: 1 });
  assert.equal(overlay.code, "reducer_rejected");
  assert.equal(overlay.classificationScope, "client");
  assert.equal(overlay.requiresClientOverlay, false);
  assert.deepEqual(overlay.clientCounts, { available: true, received: 2, decoded: 2, applied: 1, source: "client-local-overlay" });
});

test("correlated tracker counts unique offsets and rejects a duplicate even after lastOffset", () => {
  const tracker = createWorkbenchKafkaDebugReplayTracker({
    mode: "correlated-v2",
    replayId: "rpl_unique_offsets",
    traceId: "trc_unique_offsets",
    offsetRange: { partition: 0, firstOffset: "10", lastOffset: "11" },
    producer: { invoked: true, sourceMatched: true, publishedCount: 2 }
  });
  markWorkbenchKafkaDebugReplayConsumerReady(tracker, { groupId: "hwlab-debug-unique", seekApplied: true });
  const observation = (offset: string, duplicate = false) => ({
    partition: 0,
    offset,
    duplicate,
    inOffsetRange: true,
    parsed: true,
    filterMatches: { traceId: true, replayId: true },
    matched: !duplicate
  });
  observeWorkbenchKafkaDebugReplayRecord(tracker, observation("10"));
  observeWorkbenchKafkaDebugReplayRecord(tracker, observation("10", true));
  observeWorkbenchKafkaDebugReplayRecord(tracker, observation("11"));
  recordWorkbenchKafkaDebugReplayDelivery(tracker, { partition: 0, offset: "10", value: {} });
  recordWorkbenchKafkaDebugReplayDelivery(tracker, { partition: 0, offset: "11", value: {} });
  markWorkbenchKafkaDebugReplayBarrierComplete(tracker);
  const result = completeWorkbenchKafkaDebugReplay(tracker, { reason: "barrier", terminalObserved: true });
  assert.equal(result.counts.scanned, 3);
  assert.equal(result.counts.barrierScanned, 2);
  assert.equal(result.barrier.uniqueOffsetCount, 2);
  assert.equal(result.rejectedByReason.duplicate_offset, 1);
  assert.equal(result.code, "barrier_duplicate_offset");
  assert.equal(result.classificationScope, "server");
  assert.equal(result.requiresClientOverlay, true);
  assert.deepEqual(result.clientCounts, {
    available: false,
    received: null,
    decoded: null,
    applied: null,
    source: "client-local-overlay-required"
  });
});

function correlatedReplay(overrides: Record<string, any> = {}) {
  return {
    mode: "correlated-v2",
    replayId: "rpl_correlated",
    traceId: "trc_correlated",
    producer: { invoked: true, sourceMatched: true, publishedCount: 2 },
    consumer: readyConsumer,
    requestedOffsetRange: { partition: 0, firstOffset: "10", lastOffset: "11" },
    barrier: { seekApplied: true, completed: true, lastOffsetObserved: true },
    rejectedByReason: {},
    counts: correlatedCounts(),
    terminalObserved: true,
    ...overrides
  };
}

function correlatedCounts() {
  return {
    scanned: 2,
    barrierScanned: 2,
    parsed: 2,
    traceMatched: 2,
    replayMatched: 2,
    matched: 2,
    delivered: 2,
    clientReceived: null,
    decoded: null,
    applied: null
  };
}
