import { test } from 'node:test';
import assert from 'node:assert/strict';
import { splitMathSegments } from './mathParse';

test('plain text with no dollars is a single text segment', () => {
  assert.deepEqual(splitMathSegments('hello world'), [{ type: 'text', value: 'hello world' }]);
});

test('empty string yields no segments', () => {
  assert.deepEqual(splitMathSegments(''), []);
});

test('inline $…$ is extracted between surrounding text', () => {
  assert.deepEqual(splitMathSegments('a $x^2$ b'), [
    { type: 'text', value: 'a ' },
    { type: 'inline', value: 'x^2' },
    { type: 'text', value: ' b' },
  ]);
});

test('block $$…$$ is extracted', () => {
  assert.deepEqual(splitMathSegments('$$block$$'), [{ type: 'block', value: 'block' }]);
});

test('block math may span newlines', () => {
  assert.deepEqual(splitMathSegments('$$\na=b\n$$'), [{ type: 'block', value: '\na=b\n' }]);
});

test('currency "$5 and $10" is NOT treated as math', () => {
  assert.deepEqual(splitMathSegments('$5 and $10'), [{ type: 'text', value: '$5 and $10' }]);
});

test('escaped \\$ never opens or closes math', () => {
  assert.deepEqual(splitMathSegments('cost \\$5 today'), [
    { type: 'text', value: 'cost $5 today' },
  ]);
  assert.deepEqual(splitMathSegments('\\$x\\$'), [{ type: 'text', value: '$x$' }]);
});

test('unbalanced single $ stays as text', () => {
  assert.deepEqual(splitMathSegments('price is $ here'), [
    { type: 'text', value: 'price is $ here' },
  ]);
});

test('unbalanced $$ stays as text', () => {
  assert.deepEqual(splitMathSegments('$$x'), [{ type: 'text', value: '$$x' }]);
});

test('inline requires non-space adjacency on both delimiters', () => {
  // Space right after opening $ -> not math.
  assert.deepEqual(splitMathSegments('$ x$'), [{ type: 'text', value: '$ x$' }]);
  // Space right before closing $ -> not math.
  assert.deepEqual(splitMathSegments('$x $'), [{ type: 'text', value: '$x $' }]);
});

test('multiple inline spans on one line', () => {
  assert.deepEqual(splitMathSegments('$a$ and $b$'), [
    { type: 'inline', value: 'a' },
    { type: 'text', value: ' and ' },
    { type: 'inline', value: 'b' },
  ]);
});

test('escaped dollar inside inline math is preserved in LaTeX', () => {
  assert.deepEqual(splitMathSegments('$a\\$b$'), [{ type: 'inline', value: 'a\\$b' }]);
});

test('closing $ followed by a digit is skipped (currency guard) then recovers', () => {
  // The first candidate closer is followed by `2` so it is skipped; the later
  // `$` closes the span.
  assert.deepEqual(splitMathSegments('$x$2 + y$'), [{ type: 'inline', value: 'x$2 + y' }]);
});

test('block and inline mixed with text', () => {
  assert.deepEqual(splitMathSegments('see $$E=mc^2$$ and $a$ ok'), [
    { type: 'text', value: 'see ' },
    { type: 'block', value: 'E=mc^2' },
    { type: 'text', value: ' and ' },
    { type: 'inline', value: 'a' },
    { type: 'text', value: ' ok' },
  ]);
});
