/**
 * 字典/词条搜索：匹配度打分、排序、关键字高亮拆分
 * 与后端 DictSearchRankService 规则对齐；mode=frontend 时由本工具排序
 */

export type DictSearchRankMode = 'backend' | 'frontend';

export type HighlightPart = { text: string; hit: boolean };

/** 与 PHP DictSearchRankService::score 对齐 */
export function scoreDictMatch(
  text: string,
  keyword: string,
  extra = '',
): number {
  const kw = String(keyword || '').trim();
  if (!kw) return 0;
  const main = String(text || '').trim();
  if (!main) return 0;
  let s = scoreOne(main, kw);
  if (extra) {
    s = Math.max(s, Math.floor(scoreOne(String(extra), kw) * 0.9));
  }
  return s;
}

function scoreOne(haystack: string, needle: string): number {
  if (haystack === needle) return 100;
  const lowerH = haystack.toLowerCase();
  const lowerN = needle.toLowerCase();
  const pos = lowerH.indexOf(lowerN);
  if (pos < 0) return 0;
  if (pos === 0) {
    const lenBonus = Math.max(0, 10 - Math.abs(haystack.length - needle.length));
    return 80 + Math.min(15, lenBonus);
  }
  return Math.max(20, 60 - Math.min(40, pos));
}

/**
 * 按匹配度降序；无关键字时保持原序
 */
export function rankByMatchScore<T>(
  items: T[],
  keyword: string,
  getText: (item: T) => string,
  getExtra?: (item: T) => string,
): Array<T & { match_score: number }> {
  const kw = String(keyword || '').trim();
  const scored = items.map((item) => {
    const score = kw
      ? scoreDictMatch(getText(item), kw, getExtra?.(item) || '')
      : 0;
    return Object.assign({}, item, { match_score: score }) as T & {
      match_score: number;
    };
  });
  if (!kw) return scored;
  return scored.sort((a, b) => {
    if (b.match_score !== a.match_score) return b.match_score - a.match_score;
    return 0;
  });
}

/**
 * 将文本按关键字拆成高亮片段（不做 HTML，便于 PC/小程序安全渲染）
 */
export function splitHighlight(
  text: string,
  keyword: string,
): HighlightPart[] {
  const raw = String(text ?? '');
  const kw = String(keyword || '').trim();
  if (!raw || !kw) return [{ text: raw, hit: false }];
  const lower = raw.toLowerCase();
  const needle = kw.toLowerCase();
  const parts: HighlightPart[] = [];
  let start = 0;
  let idx = lower.indexOf(needle, start);
  while (idx >= 0) {
    if (idx > start) {
      parts.push({ text: raw.slice(start, idx), hit: false });
    }
    parts.push({ text: raw.slice(idx, idx + kw.length), hit: true });
    start = idx + kw.length;
    idx = lower.indexOf(needle, start);
  }
  if (start < raw.length) {
    parts.push({ text: raw.slice(start), hit: false });
  }
  return parts.length ? parts : [{ text: raw, hit: false }];
}

let cachedRankMode: DictSearchRankMode | null = null;
/** 多气泡实例共享同一请求，避免进页 N 次 get-by-keys */
let rankModeFetchPromise: Promise<DictSearchRankMode> | null = null;

/** 写入缓存（从系统配置或接口响应读取后调用） */
export function setDictSearchRankMode(mode: string | undefined | null) {
  cachedRankMode = mode === 'frontend' ? 'frontend' : 'backend';
}

export function getDictSearchRankMode(): DictSearchRankMode {
  return cachedRankMode || 'backend';
}

export function isDictSearchRankModeLoaded(): boolean {
  return cachedRankMode != null;
}

/**
 * 确保已加载匹配度模式：已缓存则跳过；并发调用共享同一 Promise
 * @param loader 真正打网取配置的函数，返回 frontend|backend
 */
export async function ensureDictSearchRankMode(
  loader: () => Promise<string | undefined | null>,
): Promise<DictSearchRankMode> {
  if (cachedRankMode != null) return cachedRankMode;
  if (!rankModeFetchPromise) {
    rankModeFetchPromise = (async () => {
      try {
        const mode = await loader();
        setDictSearchRankMode(mode);
      } catch {
        setDictSearchRankMode('backend');
      }
      return cachedRankMode || 'backend';
    })();
  }
  return rankModeFetchPromise;
}

/**
 * 按当前模式决定是否前端重排；有关键字时保证按匹配度降序，并尽量带上可展示的 match_score
 */
export function applyDictRankIfNeeded<T>(
  items: T[],
  keyword: string,
  getText: (item: T) => string,
  getExtra?: (item: T) => string,
  modeFromApi?: string,
): Array<T & { match_score: number }> {
  if (modeFromApi === 'frontend' || modeFromApi === 'backend') {
    setDictSearchRankMode(modeFromApi);
  }
  const mode = getDictSearchRankMode();
  const kw = String(keyword || '').trim();
  if (mode === 'frontend') {
    return rankByMatchScore(items, keyword, getText, getExtra);
  }
  // backend：保留接口分数；若有关键字却全是 0（漏打分/合并未打分），前端补算
  const mapped = items.map((item: any) => ({
    ...item,
    match_score: Number(item?.match_score || 0),
  })) as Array<T & { match_score: number }>;
  if (!kw) return mapped;
  const hasPositive = mapped.some((i) => Number(i.match_score) > 0);
  if (!hasPositive) {
    return rankByMatchScore(items, keyword, getText, getExtra);
  }
  return mapped.sort((a, b) => {
    if (b.match_score !== a.match_score) return b.match_score - a.match_score;
    return 0;
  });
}
