import { compareBreaksLexicographically } from '../core/index';
import type { WidgetBeam } from './types';

function compareTieKey(a: number[], b: number[]): number {
  const n = Math.min(a.length, b.length);
  for (let i = 0; i < n; i++) {
    const av = a[i] ?? 0;
    const bv = b[i] ?? 0;
    if (av < bv) return -1;
    if (av > bv) return 1;
  }
  if (a.length < b.length) return -1;
  if (a.length > b.length) return 1;
  return 0;
}

/**
 * BeamK 排序（确定性）：
 * - score 越大越优
 * - tieKey 越小越优
 * - breaks 字典序更小者更优（11.0A）
 */
export function compareBeams(a: WidgetBeam, b: WidgetBeam): number {
  if (a.score !== b.score) return b.score - a.score;
  const t = compareTieKey(a.tieKey, b.tieKey);
  if (t !== 0) return t;
  return compareBreaksLexicographically(a.breaks, b.breaks);
}

function breaksKey(breaks: number[]): string {
  return breaks.join(',');
}

export function insertBeamTopK(list: WidgetBeam[], cand: WidgetBeam, k: number): WidgetBeam[] {
  const K = Math.max(1, k | 0);
  const out = list.slice();

  const key = breaksKey(cand.breaks);
  const idx = out.findIndex((x) => breaksKey(x.breaks) === key);
  if (idx >= 0) {
    const existing = out[idx]!;
    if (compareBeams(cand, existing) < 0) return out;
    out[idx] = cand;
  } else {
    out.push(cand);
  }

  out.sort(compareBeams);
  if (out.length > K) out.length = K;
  return out;
}

