// Copyright (c) 2026 defconxt. All rights reserved.
// Licensed under AGPL-3.0 — see LICENSE file for details.
// NERF is a trademark of defconxt.

/**
 * End-to-end verification for nerf_lookup tool registrations.
 *
 * Exercises both the KnowledgeStore search API directly and the MCP
 * server's nerf_lookup dispatch. Confirms the pi extension registers
 * the lookup tool and the MCP server exposes nerf_lookup with the
 * correct schema.
 *
 * Usage:
 *   node cli/lib/knowledge/verify-lookup.js
 *
 * Exit 0 if all checks pass, 1 if any fail, 2 on fatal error.
 */

import { KnowledgeStore } from './store.js';

// ---------------------------------------------------------------------------
// Test harness (matches verify.js pattern)
// ---------------------------------------------------------------------------

let passed = 0;
let failed = 0;

function pass(name) {
  console.log(`PASS: ${name}`);
  passed++;
}

function fail(name, reason) {
  console.log(`FAIL: ${name} — ${reason}`);
  failed++;
}

// ---------------------------------------------------------------------------
// Checks
// ---------------------------------------------------------------------------

async function main() {
  // ---- 1. KnowledgeStore direct search ----
  let store;
  try {
    store = new KnowledgeStore();
  } catch (err) {
    console.log(`FAIL: store-init — could not open KnowledgeStore: ${err.message}`);
    console.log('\nHint: run `nerf index --rebuild` to create the knowledge index.');
    process.exit(1);
  }

  // Early exit when index exists but is empty (or was just auto-created)
  try {
    const { total } = store.stats();
    if (total === 0) {
      store.close();
      console.log('SKIP: knowledge index is empty (0 chunks). DB-dependent checks cannot run.');
      console.log('Hint: run `nerf index --rebuild` to populate the knowledge index.');
      process.exit(1);
    }
  } catch {
    store.close();
    console.log('SKIP: could not read knowledge index stats. DB may be corrupt or missing tables.');
    console.log('Hint: run `nerf index --rebuild` to recreate the knowledge index.');
    process.exit(1);
  }

  try {
    const results = store.search('SQL injection', { limit: 3 });
    if (!Array.isArray(results)) {
      fail('direct-search', `expected array, got ${typeof results}`);
    } else if (results.length === 0) {
      fail('direct-search', 'returned 0 results for "SQL injection"');
    } else {
      const first = results[0];
      const hasFields = first.source_file && first.section_heading
        && typeof first.content === 'string' && first.adjusted_rank != null;
      if (hasFields) {
        pass(`direct-search (${results.length} results, top: ${first.source_file})`);
      } else {
        fail('direct-search', `missing fields on result: source_file=${first.source_file}, section_heading=${first.section_heading}, content=${typeof first.content}, rank=${first.adjusted_rank}`);
      }
    }
  } catch (err) {
    fail('direct-search', `threw: ${err.message}`);
  }

  // ---- 2. Domain-filtered search ----
  try {
    const results = store.search('authentication bypass', { domain: 'application-security', limit: 3 });
    if (!Array.isArray(results)) {
      fail('domain-filter', `expected array, got ${typeof results}`);
    } else if (results.length === 0) {
      // If no results match this domain, that's informational — not a code bug
      // Check if the domain exists at all
      const stats = store.stats();
      if (stats.byDomain['application-security']) {
        fail('domain-filter', `0 results for "authentication bypass" in application-security (${stats.byDomain['application-security']} chunks in domain)`);
      } else {
        // Domain doesn't exist in index — skip, not a registration bug
        pass('domain-filter (domain not indexed — vacuously correct, filter works)');
      }
    } else {
      const allMatch = results.every(r => r.domain === 'application-security');
      if (allMatch) {
        pass(`domain-filter (${results.length} results, all domain=application-security)`);
      } else {
        const mismatch = results.find(r => r.domain !== 'application-security');
        fail('domain-filter', `result has domain="${mismatch.domain}" instead of "application-security"`);
      }
    }
  } catch (err) {
    fail('domain-filter', `threw: ${err.message}`);
  }

  // ---- 3. Mode-boosted search ----
  try {
    const results = store.search('privilege escalation', { mode: 'red', limit: 5 });
    if (!Array.isArray(results)) {
      fail('mode-boost', `expected array, got ${typeof results}`);
    } else if (results.length === 0) {
      fail('mode-boost', 'returned 0 results for "privilege escalation" with mode=red');
    } else {
      pass(`mode-boost (${results.length} results with mode=red boost)`);
    }
  } catch (err) {
    fail('mode-boost', `threw: ${err.message}`);
  }

  // ---- 4. Graceful empty query ----
  try {
    const results = store.search('');
    if (Array.isArray(results) && results.length === 0) {
      pass('empty-query (returned [] without throwing)');
    } else {
      fail('empty-query', `expected [], got ${JSON.stringify(results).substring(0, 100)}`);
    }
  } catch (err) {
    fail('empty-query', `threw: ${err.message}`);
  }

  // ---- 5. mode-differentiation (RED vs BLUE must return different top-1) ----
  try {
    const redResults = store.search('authentication bypass', { mode: 'red', limit: 3 });
    const blueResults = store.search('authentication bypass', { mode: 'blue', limit: 3 });
    if (redResults.length === 0 || blueResults.length === 0) {
      fail('mode-differentiation', `insufficient results — RED: ${redResults.length}, BLUE: ${blueResults.length}`);
    } else if (redResults[0].chunk_id !== blueResults[0].chunk_id) {
      pass(`mode-differentiation (RED top: ${redResults[0].source_file} § ${redResults[0].section_heading}, BLUE top: ${blueResults[0].source_file} § ${blueResults[0].section_heading})`);
    } else {
      fail('mode-differentiation', `RED and BLUE top-1 chunk_ids match — affinity not differentiating. Both: ${redResults[0].source_file} § ${redResults[0].section_heading} (chunk_id: ${redResults[0].chunk_id})`);
    }
  } catch (err) {
    fail('mode-differentiation', `threw: ${err.message}`);
  }

  store.close();

  // ---- 6-8. MCP and pi-extension checks removed ----
  // Old cli/lib/mcp/server.js replaced by packages/mcp-server/
  // Old cli/lib/pi-extension/ replaced by src/resources/extensions/nerf/
  // These integration checks will be rewritten in S03 against the new modules.
  console.log('SKIP: mcp-schema, mcp-dispatch, pi-extension-lookup (modules migrated to nerf layout)');

  // ---- Summary ----
  console.log(`\n${'='.repeat(50)}`);
  console.log(`Results: ${passed} passed, ${failed} failed out of ${passed + failed} checks`);
  console.log('='.repeat(50));

  process.exit(failed > 0 ? 1 : 0);
}

main().catch((err) => {
  console.error('FATAL:', err);
  process.exit(2);
});
