import fs from 'node:fs';
import path from 'node:path';

import {
  canonicalizeStructuredFields,
  countStructuredCharacters,
  mergeStructuredFields,
  parseSerializedStructuredFields,
  serializeStructuredFields,
  splitStructuredTranslation,
  validateStructuredFields,
} from '../../../utils/structuredFields';

describe('structured async field contract', () => {
  it('canonicalizes keys and counts every field', () => {
    const fields = canonicalizeStructuredFields({ zeta: '123', alpha: '<b>12</b>', content: 'body' });

    expect(Object.keys(fields)).toEqual(['alpha', 'content', 'zeta']);
    expect(countStructuredCharacters(fields)).toBe(9);
  });

  it('counts visible Unicode characters and ignores quoted HTML attributes', () => {
    expect(countStructuredCharacters({ content: '<p title="1>2">😀</p>' })).toBe(1);
  });

  it('matches the PHP character-count fixtures exactly', () => {
    const fixturePath = path.resolve(
      __dirname,
      '../../../../../../plugins/international-press-zone/tests/fixtures/character-count-fixtures.json'
    );
    const fixtures = JSON.parse(fs.readFileSync(fixturePath, 'utf8')) as Array<{ name: string; value: string; characters: number }>;

    for (const fixture of fixtures) {
      expect(countStructuredCharacters({ value: fixture.value })).toBe(fixture.characters);
    }
  });

  it('accepts HTML-rich values when sanitized aggregate stays within the limit', () => {
    const value = Array.from({ length: 600 }, () => `<p title="${'x'.repeat(100)}">visible</p>`).join('');

    expect(() => mergeStructuredFields({ content: value }, undefined, 10_000)).not.toThrow();
  });

  it('rejects reserved custom keys and aggregate overflow', () => {
    expect(() => validateStructuredFields({ title: 'collision' }, 100)).toThrow('reserved');
    expect(() => mergeStructuredFields({ title: '1234' }, { custom: '5678' }, 7)).toThrow('character limit');
  });

  it('round-trips marked structured payloads without classifying legacy JSON', () => {
    const payload = serializeStructuredFields({ content: 'Body', title: 'Title' });

    expect(parseSerializedStructuredFields(payload)).toEqual({ content: 'Body', title: 'Title' });
    expect(parseSerializedStructuredFields('{"foo":"bar"}')).toBeUndefined();
  });
  it('splits core aliases from translated custom fields', () => {
    expect(splitStructuredTranslation({ content: 'Body', title: 'Title', custom: 'Value' })).toEqual({
      translatedTitle: 'Title',
      translatedExcerpt: undefined,
      translatedContent: 'Body',
      translatedFields: { custom: 'Value' },
    });
  });
});
