import { describe, it, expect } from 'vitest';
import {
  RichTextBlock,
  deepCopyBlock,
  emptyBlock,
  isBlockEmpty,
  placeholderKeysIn,
} from './rich-text';

const block = (): RichTextBlock => ({
  paragraphs: [
    {
      nodes: [
        { type: 'text', text: 'Beste ' },
        { type: 'placeholder', key: 'naam' },
      ],
    },
    {
      nodes: [
        { type: 'placeholder', key: 'datum' },
        { type: 'placeholder', key: 'naam' },
      ],
    },
  ],
});

describe('rich-text', () => {
  it('emptyBlock is one empty paragraph and reads as empty', () => {
    expect(emptyBlock()).toEqual({ paragraphs: [{ nodes: [] }] });
    expect(isBlockEmpty(emptyBlock())).toBe(true);
  });

  it('isBlockEmpty is false when any placeholder or non-blank text exists', () => {
    expect(isBlockEmpty({ paragraphs: [{ nodes: [{ type: 'text', text: '   ' }] }] })).toBe(true);
    expect(isBlockEmpty({ paragraphs: [{ nodes: [{ type: 'placeholder', key: 'x' }] }] })).toBe(
      false,
    );
    expect(isBlockEmpty({ paragraphs: [{ nodes: [{ type: 'text', text: 'hoi' }] }] })).toBe(false);
  });

  it('placeholderKeysIn walks in document order, keeping duplicates', () => {
    expect(placeholderKeysIn(block())).toEqual(['naam', 'datum', 'naam']);
  });

  it('deepCopyBlock is an independent value copy (frozen snapshot)', () => {
    const original = block();
    const copy = deepCopyBlock(original);
    expect(copy).toEqual(original);
    expect(copy).not.toBe(original);
    expect(copy.paragraphs[0]).not.toBe(original.paragraphs[0]);
    // Mutating the copy must not touch the original — proves no shared reference.
    (copy.paragraphs[0].nodes as { type: 'text'; text: string }[])[0] = {
      type: 'text',
      text: 'CHANGED',
    };
    expect(placeholderKeysIn(original)).toEqual(['naam', 'datum', 'naam']);
    expect((original.paragraphs[0].nodes[0] as { text: string }).text).toBe('Beste ');
  });
});
