import { describe, expect, it } from 'vitest';

import { segmentGraphemes } from '../index';

const REQUIRED_SINGLE_CLUSTER_CASES: Array<{ name: string; input: string }> = [
  { name: 'ZWJ family', input: '👨‍👩‍👧‍👦' },
  { name: 'flag', input: '🇸🇬' },
  { name: 'skin tone', input: '👍🏽' },
  { name: 'ZWJ + variation', input: '😮‍💨' },
  { name: 'combining mark', input: 'e\u0301' }, // é（组合形式）
];

describe('textWrap grapheme-segmentation', () => {
  it('基础性质：空字符串 -> []', () => {
    const out = segmentGraphemes('', 'PREFERRED');
    expect(out.clusters).toEqual([]);
    expect(out.clusters.join('')).toBe('');
  });

  it('基础性质：可逆性（clusters.join("") === input）', () => {
    const input = '我好累😮‍💨';
    const out = segmentGraphemes(input, 'PREFERRED');
    expect(out.clusters.join('')).toBe(input);
  });

  it('基础性质：确定性（同输入同输出）', () => {
    const input = '👨‍👩‍👧‍👦🇸🇬👍🏽😮‍💨e\u0301';
    const a = segmentGraphemes(input, 'PREFERRED');
    const b = segmentGraphemes(input, 'PREFERRED');
    expect(a).toEqual(b);
  });

  it('必测样例：在 PREFERRED 下必须“不拆”为单个 cluster', () => {
    for (const c of REQUIRED_SINGLE_CLUSTER_CASES) {
      const out = segmentGraphemes(c.input, 'PREFERRED');
      expect(out.clusters.join('')).toBe(c.input);
      expect(out.clusters.length).toBe(1);
      expect(out.clusters[0]).toBe(c.input);
    }
  });

  it('必测样例：在强制 FALLBACK 下必须“不拆”为单个 cluster', () => {
    for (const c of REQUIRED_SINGLE_CLUSTER_CASES) {
      const out = segmentGraphemes(c.input, 'FALLBACK');
      expect(out.meta.strategy).toBe('FALLBACK');
      expect(out.meta.hadFallback).toBe(true);
      expect(out.clusters.join('')).toBe(c.input);
      expect(out.clusters.length).toBe(1);
      expect(out.clusters[0]).toBe(c.input);
    }
  });

  it('跨策略一致性：若 Intl.Segmenter 可用，则 PREFERRED 与 FALLBACK 输出应一致', () => {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const hasIntl = typeof (globalThis as any)?.Intl?.Segmenter === 'function';
    if (!hasIntl) return;

    for (const c of REQUIRED_SINGLE_CLUSTER_CASES) {
      const preferred = segmentGraphemes(c.input, 'PREFERRED');
      const fallback = segmentGraphemes(c.input, 'FALLBACK');
      expect(preferred.clusters).toEqual(fallback.clusters);
    }
  });
});

