import { getConfig } from './config.mjs';

let _available = false;
let _db = null;

/**
 * Initialize the vector cache. Attempts to load the sqlite-vec extension.
 * If sqlite-vec is not installed, logs a warning and degrades gracefully.
 * @param {import('better-sqlite3').Database} db - better-sqlite3 database instance
 */
export function initVectorCache(db) {
  _db = db;
  _available = false;

  try {
    db.loadExtension('vec0');
    db.exec(`
      CREATE VIRTUAL TABLE IF NOT EXISTS vec_cache USING vec0(
        id TEXT PRIMARY KEY,
        text TEXT,
        embedding float[768],
        metadata TEXT
      );
    `);
    _available = true;
    console.log('[vector-cache] sqlite-vec loaded, vec_cache table ready');
  } catch (err) {
    console.warn('[vector-cache] sqlite-vec extension not available — vector cache disabled:', err.message);
  }
}

/**
 * Returns whether sqlite-vec loaded successfully and vec_cache is usable.
 * @returns {boolean}
 */
export function isAvailable() {
  return _available;
}

/**
 * Embed text using the configured Ollama embeddings endpoint.
 * Returns null if Ollama is unreachable or an error occurs.
 * @param {string} text - text to embed
 * @returns {Promise<Float32Array|null>}
 */
export async function embed(text) {
  const config = getConfig();
  const vectorConfig = config.vector || {};
  const endpoint = vectorConfig.embeddingEndpoint || 'http://localhost:11434';
  const model = vectorConfig.embeddingModel || 'nomic-embed-text';

  try {
    const res = await fetch(`${endpoint}/api/embeddings`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ model, prompt: text })
    });

    if (!res.ok) {
      console.warn(`[vector-cache] Ollama embeddings returned status ${res.status}`);
      return null;
    }

    const data = await res.json();
    if (!data.embedding || !Array.isArray(data.embedding)) {
      console.warn('[vector-cache] Ollama response missing embedding array');
      return null;
    }

    return new Float32Array(data.embedding);
  } catch (err) {
    console.warn('[vector-cache] Ollama embedding request failed:', err.message);
    return null;
  }
}

/**
 * Store an embedding in the vec_cache table.
 * No-op if sqlite-vec is not available.
 * @param {string} id - unique identifier
 * @param {string} text - original text
 * @param {Float32Array} vector - embedding vector
 * @param {object|string} metadata - optional metadata (will be JSON-stringified if object)
 */
export function store(id, text, vector, metadata = null) {
  if (!_available || !_db) return;

  try {
    const metaStr = typeof metadata === 'string' ? metadata : JSON.stringify(metadata);
    const stmt = _db.prepare(
      'INSERT OR REPLACE INTO vec_cache(id, text, embedding, metadata) VALUES (?, ?, ?, ?)'
    );
    stmt.run(id, text, Buffer.from(vector.buffer), metaStr);
  } catch (err) {
    console.warn('[vector-cache] store failed:', err.message);
  }
}

/**
 * Search for similar vectors in vec_cache.
 * Embeds the query text, then performs vector similarity search.
 * Returns empty array if sqlite-vec is not available or embedding fails.
 * @param {string} query - query text to search for
 * @param {number} topK - number of results to return (default 5)
 * @returns {Promise<Array<{id: string, text: string, metadata: string, distance: number}>>}
 */
export async function search(query, topK = 5) {
  if (!_available || !_db) return [];

  try {
    const vector = await embed(query);
    if (!vector) return [];

    const stmt = _db.prepare(`
      SELECT id, text, metadata, distance
      FROM vec_cache
      WHERE embedding MATCH ?
      ORDER BY distance
      LIMIT ?
    `);
    const rows = stmt.all(Buffer.from(vector.buffer), topK);
    return rows.map(row => ({
      id: row.id,
      text: row.text,
      metadata: row.metadata,
      distance: row.distance
    }));
  } catch (err) {
    console.warn('[vector-cache] search failed:', err.message);
    return [];
  }
}

/**
 * Delete all entries from the vec_cache table.
 * No-op if sqlite-vec is not available.
 */
export function clearCache() {
  if (!_available || !_db) return;

  try {
    _db.exec('DELETE FROM vec_cache');
    console.log('[vector-cache] cache cleared');
  } catch (err) {
    console.warn('[vector-cache] clearCache failed:', err.message);
  }
}
