import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { extractPromptsFromFile } from '../src/backfill/scan';

function writeFixture(lines: unknown[]): string {
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-scan-test-'));
  const file = path.join(dir, 'session.jsonl');
  fs.writeFileSync(file, lines.map((l) => JSON.stringify(l)).join('\n'));

  return file;
}

const humanEntry = (overrides: Record<string, unknown> = {}) => ({
  type: 'user',
  isSidechain: false,
  uuid: 'msg-1',
  sessionId: 'sess-1',
  cwd: '/some/project',
  timestamp: '2026-08-20T10:00:00.000Z',
  message: { content: [{ type: 'text', text: 'hello' }] },
  ...overrides,
});

test('extracts a genuine human-typed prompt', () => {
  const file = writeFixture([humanEntry()]);
  const result = extractPromptsFromFile(file, '2026-08-01T00:00:00.000Z');

  assert.equal(result.length, 1);
  assert.equal(result[0].text, 'hello');
  assert.equal(result[0].sessionId, 'sess-1');
});

test('joins multiple text blocks (e.g. injected IDE context + the real prompt)', () => {
  const file = writeFixture([
    humanEntry({
      message: {
        content: [
          { type: 'text', text: '<ide_opened_file>foo.ts</ide_opened_file>' },
          { type: 'text', text: 'fix the bug' },
        ],
      },
    }),
  ]);
  const result = extractPromptsFromFile(file, '2026-08-01T00:00:00.000Z');

  assert.equal(result.length, 1);
  assert.match(result[0].text, /fix the bug/);
});

test('excludes tool-result "user" entries (not real human prompts)', () => {
  const file = writeFixture([
    humanEntry({
      uuid: 'msg-2',
      message: { content: [{ type: 'tool_result', tool_use_id: 'x', content: 'some output' }] },
    }),
  ]);
  const result = extractPromptsFromFile(file, '2026-08-01T00:00:00.000Z');

  assert.equal(result.length, 0);
});

test('excludes sidechain (sub-agent) entries', () => {
  const file = writeFixture([humanEntry({ isSidechain: true })]);
  const result = extractPromptsFromFile(file, '2026-08-01T00:00:00.000Z');

  assert.equal(result.length, 0);
});

test('excludes entries older than the since cutoff', () => {
  const file = writeFixture([humanEntry({ timestamp: '2026-07-01T00:00:00.000Z' })]);
  const result = extractPromptsFromFile(file, '2026-08-01T00:00:00.000Z');

  assert.equal(result.length, 0);
});

test('excludes non-user entry types', () => {
  const file = writeFixture([humanEntry({ type: 'assistant' })]);
  const result = extractPromptsFromFile(file, '2026-08-01T00:00:00.000Z');

  assert.equal(result.length, 0);
});

test('skips malformed JSON lines without throwing', () => {
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-scan-test-'));
  const file = path.join(dir, 'session.jsonl');
  fs.writeFileSync(file, `not json\n${JSON.stringify(humanEntry())}\n`);

  const result = extractPromptsFromFile(file, '2026-08-01T00:00:00.000Z');

  assert.equal(result.length, 1);
});

test('excludes synthetic "[Request interrupted by user]" system markers', () => {
  const file = writeFixture([
    humanEntry({ message: { content: [{ type: 'text', text: '[Request interrupted by user]' }] } }),
    humanEntry({ uuid: 'msg-3', message: { content: [{ type: 'text', text: '[Request interrupted by user for tool use]' }] } }),
  ]);
  const result = extractPromptsFromFile(file, '2026-08-01T00:00:00.000Z');

  assert.equal(result.length, 0);
});

test('skips a prompt that is entirely injected content and becomes empty', () => {
  const file = writeFixture([
    humanEntry({
      message: { content: [{ type: 'text', text: '   ' }] },
    }),
  ]);
  const result = extractPromptsFromFile(file, '2026-08-01T00:00:00.000Z');

  assert.equal(result.length, 0);
});
