import { findKGEntities, getKGContext } from './knowledge-graph.mjs';
import { askLLM, pickModel } from './llm.mjs';
import { parseLLMJson } from './json-utils.mjs';

export async function semanticSearch(query, workspaceId = null, opts = {}) {
  const candidateLimit = opts.candidateLimit || 30;
  const candidates = findKGEntities(query, { workspaceId, limit: candidateLimit });
  if (!candidates.length) return [];

  // If few candidates, return directly with score 100 (no reranking needed)
  if (candidates.length <= 5) {
    return candidates.map(c => ({ entity: c, relevanceScore: 100, reason: 'Direct match' }));
  }

  // LLM reranking
  try {
    const entityList = candidates.map(c => `${c.id}: ${c.name} (${c.type})${c.metadata ? ' - ' + String(c.metadata).slice(0, 80) : ''}`).join('\n');
    const prompt = `Rank these entities by relevance to the query: "${query}"

Entities:
${entityList}

Return JSON: { "ranked": [{ "id": entityId, "score": 0-100, "reason": "brief reason" }] }
Only include entities with score > 20. Max 10 results. Sort by score descending.`;

    const response = await askLLM(prompt, { model: pickModel('extract') });
    const parsed = parseLLMJson(response);
    if (!parsed.ok) throw new Error('Parse failed');

    const ranked = (parsed.data.ranked || [])
      .map(r => {
        const entity = candidates.find(c => c.id === r.id);
        if (!entity) return null;
        return { entity, relevanceScore: r.score || 0, reason: r.reason || '' };
      })
      .filter(Boolean)
      .sort((a, b) => b.relevanceScore - a.relevanceScore);

    return ranked;
  } catch {
    // Fallback: return all candidates with uniform score
    return candidates.slice(0, 10).map(c => ({ entity: c, relevanceScore: 50, reason: 'FTS5 match (no reranking)' }));
  }
}

export async function findRelevantContext(query, maxTokens = 2000) {
  const results = await semanticSearch(query);
  if (!results.length) return '';

  // Use getKGContext for the top entities
  const topEntities = results.slice(0, 5);
  let context = `## Relevant Knowledge\nFound ${results.length} relevant entities for "${query}":\n\n`;

  for (const r of topEntities) {
    context += `- **${r.entity.name}** (${r.entity.type}) [relevance: ${r.relevanceScore}%]`;
    if (r.reason) context += ` — ${r.reason}`;
    context += '\n';
  }

  // Truncate to approximate maxTokens (4 chars per token)
  const maxChars = maxTokens * 4;
  if (context.length > maxChars) {
    context = context.slice(0, maxChars) + '\n...(truncated)';
  }

  return context;
}
