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

import type { Token } from '../../core/types';
import { normalizeWhitespace, tokenizeEN } from '../../core/index';
import { segmentGraphemes } from '../../grapheme/index';
import { wrapText } from '../../index';
import { GOLDEN_CASES } from '../fixtures';

function tokenizeTC(normalizedText: string): Token[] {
  const { clusters } = segmentGraphemes(normalizedText, 'PREFERRED');
  const tokens: Token[] = [];
  let idx = 0;
  for (const c of clusters) {
    const start = idx;
    idx += c.length;
    tokens.push({ text: c, start, end: idx });
  }
  return tokens;
}

async function wrapTextHarness(args: {
  text: string;
  lang: 'TC' | 'EN';
  context: 'APP' | 'WIDGET';
  availableWidth: number;
  maxLines: number;
}): Promise<{ ok: true; lines: string[]; wrappedText: string } | { ok: false; detail: any }> {
  const out = await wrapText({
    text: args.text,
    lang: args.lang,
    context: args.context,
    availableWidth: args.availableWidth,
    maxLines: args.maxLines,
    fontSpec: { fontFamily: 'PingFangSC-Regular', fontWeight: '400', fontSize: 16 },
    measureWidthImpl: async ({ text }) => text.length,
    contextProfile: `${args.context}|golden`,
    lineMode: 'AUTO',
    debug: true,
  });

  // wrapText 统一返回成功形态；若进入 SYSTEM_DEFAULT 等兜底，meta 会标记
  return { ok: true, lines: out.lines, wrappedText: out.wrappedText };
}

describe('textWrap golden-tests', () => {
  for (const c of GOLDEN_CASES) {
    it(`golden:${c.id}`, async () => {
      const res = await wrapTextHarness({
        text: c.text,
        lang: c.lang,
        context: c.context,
        availableWidth: c.availableWidth,
        maxLines: c.maxLines,
      });

      if (!res.ok) {
        throw new Error(`golden case failed: ${c.id}\n${JSON.stringify(res.detail, null, 2)}`);
      }
      if (res.ok) {
        expect(res.lines).toEqual(c.expected.lines);
        expect(res.wrappedText).toBe(c.expected.wrappedText);
      }
    });
  }

  it('property: 确定性（同输入多次调用一致）', async () => {
    const args = { text: 'I am so tired', lang: 'EN' as const, context: 'APP' as const, availableWidth: 6, maxLines: 2 };
    const a = await wrapTextHarness(args);
    const b = await wrapTextHarness(args);
    const c = await wrapTextHarness(args);
    expect(a).toEqual(b);
    expect(b).toEqual(c);
  });

  it('property: 近似单调性（availableWidth 变小不会让最大行宽变大）', async () => {
    const base = { text: 'I am so tired', lang: 'EN' as const, context: 'APP' as const, maxLines: 2 };
    const wide = await wrapTextHarness({ ...base, availableWidth: 20 });
    const narrow = await wrapTextHarness({ ...base, availableWidth: 7 });

    if (!wide.ok || !narrow.ok) {
      throw new Error(`property failed: expected both ok\nwide=${JSON.stringify(wide)}\nnarrow=${JSON.stringify(narrow)}`);
    }

    const maxW = (lines: string[]) => Math.max(...lines.map((s) => s.length));
    expect(maxW(narrow.lines)).toBeLessThanOrEqual(maxW(wide.lines));
  });

  it('property: maxLines 不变差（maxLines 增加不应从可解变无解）', async () => {
    const base = { text: 'I am so tired', lang: 'EN' as const, context: 'APP' as const, availableWidth: 7 };
    const a = await wrapTextHarness({ ...base, maxLines: 2 });
    const b = await wrapTextHarness({ ...base, maxLines: 3 });

    expect(a.ok).toBe(true);
    expect(b.ok).toBe(true);
  });
});

