'use strict';

function stripSearchMarkup(value) {
  return String(value || '').replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
}

function normalizeTerm(value) {
  return String(value || '').toLowerCase().replace(/[^a-z0-9_-]/g, '');
}

function countSearchTermHits(text, terms) {
  const haystack = stripSearchMarkup(text).toLowerCase();
  const seen = new Set();
  for (const term of terms || []) {
    const clean = normalizeTerm(term);
    if (clean.length < 2 || seen.has(clean)) continue;
    if (haystack.includes(clean)) seen.add(clean);
  }
  return seen.size;
}

function messageSearchCoverage(match, terms) {
  const termCount = Math.max(0, (terms || []).filter(t => normalizeTerm(t).length >= 2).length);
  const termHits = Number(match?.termHits ?? countSearchTermHits(match?.snippet || match?.h_content || match?.content || '', terms));
  return {
    termCount,
    termHits,
    coverage: termCount > 0 ? termHits / termCount : 0,
  };
}

function messageSearchBoost(match, plan = {}) {
  const terms = plan.terms || [];
  const { termCount, termHits, coverage } = messageSearchCoverage(match, terms);
  const rank = Math.max(0, Number(match?.rank || 0));
  const userPromptBonus = String(match?.role || '').toLowerCase() === 'user' ? 0.035 : 0;
  const rankBonus = rank < 5 ? (5 - rank) * 0.012 : 0;

  let boost = 0;
  if (termCount >= 2) {
    if (coverage >= 0.8) boost += 0.18;
    else if (termHits >= 2 && coverage >= 0.5) boost += 0.10;
    else if (termHits >= 2 && rank <= 2) boost += 0.035;
  } else if (termHits > 0 && rank <= 2) {
    boost += 0.025;
  }

  boost += Math.min(termHits, 4) * 0.012;
  boost += rankBonus + userPromptBonus;
  return Math.min(0.30, boost);
}

function isStrongMessageMatch(match, plan = {}) {
  const { termCount, termHits, coverage } = messageSearchCoverage(match, plan.terms || []);
  return termCount >= 2 && termHits >= 2 && (coverage >= 0.5 || Number(match?.rank || 0) <= 2);
}

function searchMatchFieldPriority(hit) {
  const field = String(hit?._matchField || '');
  if (field === 'session_id') return 100;
  if (hit?._isExactTitle) return 95;
  if (field === 'session_reference') return 93;
  if (field === 'message' && hit?._messageStrong) return 92;
  if (field === 'title') return 90;
  if (field === 'message') return 80;
  if (field === 'firstMessage') return 70;
  if (field === 'project' || field === 'gitBranch') return 60;
  if (field === 'semantic') return 40;
  return field ? 30 : 0;
}

module.exports = {
  countSearchTermHits,
  isStrongMessageMatch,
  messageSearchBoost,
  messageSearchCoverage,
  normalizeTerm,
  searchMatchFieldPriority,
  stripSearchMarkup,
};
