import type { Breakpoint, BreakpointMeta, GenerateBreakpointsInput } from './types';
import { generateEnCandidates } from './enCandidates';
import { generateTcCandidates } from './tcCandidates';
import { buildMeta, dedupByPos, filterForbiddenBreakRanges, pruneTcCandidates } from './filterAndDedup';

/**
 * 生成候选断点（确定性）
 *
 * 统一口径：
 * - 只输出 `pos ∈ [1, N-1]`
 * - forbiddenBreakRanges 使用闭区间过滤：start <= pos && pos <= end
 * - 去重按 priority 优先；priority 相同按 kind 固定序：PUNCT > SPACE > BALANCE > OTHER
 * - TC 超过上限时按固定排序裁剪，然后最终按 pos 升序输出
 */
export function generateBreakpoints(input: GenerateBreakpointsInput): { breakpoints: Breakpoint[]; meta: BreakpointMeta } {
  const tokens = input.tokens ?? [];
  const n = tokens.length;
  const lang = input.lang;

  if (n <= 1) {
    return { breakpoints: [], meta: buildMeta(0, 0) };
  }

  let raw: Breakpoint[] = [];
  let ideals: number[] = [];

  if (lang === 'EN') {
    raw = generateEnCandidates(tokens);
  } else {
    const out = generateTcCandidates(tokens, input.maxLines, {
      tcPunctuations: input.config.tcPunctuations,
      balanceRange: input.config.balanceRange,
    });
    raw = out.candidates;
    ideals = out.idealPositions;
  }

  const originalCount = raw.length;

  // 过滤 forbiddenBreakRanges（闭区间）
  let filtered = filterForbiddenBreakRanges(raw, input.constraints);

  // 去重（同 pos 保留最佳）
  filtered = dedupByPos(filtered);

  // TC 裁剪（规模上限）
  if (lang === 'TC') {
    const max = Math.max(0, input.config.tcMaxCandidateBreaks | 0);
    if (max > 0) {
      filtered = pruneTcCandidates(filtered, ideals, max);
    }
  }

  // 最终按 pos 升序输出
  filtered.sort((a, b) => a.pos - b.pos);

  return { breakpoints: filtered, meta: buildMeta(originalCount, filtered.length) };
}

