/**
 * RuVector Database Initialization
 *
 * Provides connection management and collection initialization for the RuVector
 * vector database used in CFN Loop v3 learning systems.
 *
 * Collections:
 * - decomposition_history: Task decomposition patterns and success metrics
 * - codebase_index: Semantic index of code files and relationships
 * - error_library: Error patterns, root causes, and fixes
 * - security_patterns: Security vulnerabilities and prevention strategies
 * - performance_patterns: Performance issues and optimization strategies
 */

import RuVector from 'ruvector';
import * as path from 'path';
import * as fs from 'fs';

let db: RuVector | null = null;

/**
 * Database configuration
 */
const DB_CONFIG = {
  path: process.env.RUVECTOR_DB_PATH || './data/ruvector.db',
  dimension: 1536, // OpenAI ada-002 / text-embedding-3-small dimension
  indexType: 'hnsw' as const, // Hierarchical Navigable Small World graph
  metric: 'cosine' as const, // Cosine similarity for semantic search
};

/**
 * Collection names
 */
export const COLLECTIONS = {
  DECOMPOSITION_HISTORY: 'decomposition_history',
  CODEBASE_INDEX: 'codebase_index',
  ERROR_LIBRARY: 'error_library',
  SECURITY_PATTERNS: 'security_patterns',
  PERFORMANCE_PATTERNS: 'performance_patterns',
} as const;

/**
 * Initialize RuVector database connection and create collections
 *
 * @returns Promise<RuVector> - Connected database instance
 * @throws Error if connection fails or collections cannot be created
 */
export async function initializeRuVector(): Promise<RuVector> {
  if (db) {
    return db;
  }

  try {
    // Ensure data directory exists
    const dataDir = path.dirname(DB_CONFIG.path);
    if (!fs.existsSync(dataDir)) {
      fs.mkdirSync(dataDir, { recursive: true });
      console.log(`Created data directory: ${dataDir}`);
    }

    // Connect to database
    const startTime = Date.now();
    db = new RuVector({
      path: DB_CONFIG.path,
      dimension: DB_CONFIG.dimension,
      indexType: DB_CONFIG.indexType,
      metric: DB_CONFIG.metric,
    });

    const connectionTime = Date.now() - startTime;
    console.log(`RuVector connected in ${connectionTime}ms`);

    if (connectionTime > 100) {
      console.warn(`⚠️ RuVector connection took ${connectionTime}ms (>100ms threshold)`);
    }

    // Create all collections
    await createCollections();

    return db;
  } catch (error) {
    console.error('Failed to initialize RuVector:', error);
    throw new Error(`RuVector initialization failed: ${error instanceof Error ? error.message : String(error)}`);
  }
}

/**
 * Create all required collections
 *
 * @throws Error if collection creation fails
 */
async function createCollections(): Promise<void> {
  if (!db) {
    throw new Error('Database not initialized');
  }

  const collections = Object.values(COLLECTIONS);
  const startTime = Date.now();

  for (const collectionName of collections) {
    try {
      // Check if collection exists
      const exists = await db.collectionExists(collectionName);

      if (!exists) {
        await db.createCollection(collectionName, {
          dimension: DB_CONFIG.dimension,
          indexType: DB_CONFIG.indexType,
          metric: DB_CONFIG.metric,
        });
        console.log(`Created collection: ${collectionName}`);
      } else {
        console.log(`Collection already exists: ${collectionName}`);
      }
    } catch (error) {
      throw new Error(
        `Failed to create collection ${collectionName}: ${error instanceof Error ? error.message : String(error)}`
      );
    }
  }

  const creationTime = Date.now() - startTime;
  console.log(`All collections ready in ${creationTime}ms`);
}

/**
 * Get the RuVector database instance
 *
 * @returns RuVector - Database instance
 * @throws Error if database is not initialized
 */
export function getRuVector(): RuVector {
  if (!db) {
    throw new Error('RuVector not initialized. Call initializeRuVector() first.');
  }
  return db;
}

/**
 * Verify database connectivity and performance
 *
 * @returns Promise<VerificationResult> - Connection and performance metrics
 */
export async function verifyConnectivity(): Promise<{
  connected: boolean;
  latency: number;
  collectionsReady: boolean;
  collections: string[];
}> {
  try {
    const startTime = Date.now();

    // Ensure database is initialized
    if (!db) {
      await initializeRuVector();
    }

    // Test basic operation (list collections)
    const collections = await db!.listCollections();
    const latency = Date.now() - startTime;

    // Verify all required collections exist
    const expectedCollections = Object.values(COLLECTIONS);
    const collectionsReady = expectedCollections.every(name =>
      collections.includes(name)
    );

    return {
      connected: true,
      latency,
      collectionsReady,
      collections,
    };
  } catch (error) {
    console.error('Connectivity verification failed:', error);
    return {
      connected: false,
      latency: -1,
      collectionsReady: false,
      collections: [],
    };
  }
}

/**
 * Benchmark basic RuVector operations
 *
 * @returns Promise<BenchmarkResults> - Performance metrics for insert and query
 */
export async function benchmarkPerformance(): Promise<{
  insertLatency: number;
  queryLatency: number;
  passed: boolean;
}> {
  if (!db) {
    await initializeRuVector();
  }

  const testCollection = 'benchmark_test';
  const threshold = 100; // 100ms requirement from plan

  try {
    // Create test collection
    await db!.createCollection(testCollection, {
      dimension: DB_CONFIG.dimension,
      indexType: DB_CONFIG.indexType,
      metric: DB_CONFIG.metric,
    });

    // Test insert performance
    const testVector = Array(DB_CONFIG.dimension).fill(0).map(() => Math.random());
    const insertStart = Date.now();
    await db!.insert(testCollection, {
      id: 'test-1',
      vector: testVector,
      metadata: { test: true },
    });
    const insertLatency = Date.now() - insertStart;

    // Test query performance
    const queryStart = Date.now();
    await db!.search(testCollection, {
      vector: testVector,
      limit: 1,
    });
    const queryLatency = Date.now() - queryStart;

    // Cleanup
    await db!.deleteCollection(testCollection);

    const passed = insertLatency < threshold && queryLatency < threshold;

    return {
      insertLatency,
      queryLatency,
      passed,
    };
  } catch (error) {
    console.error('Benchmark failed:', error);
    throw new Error(`Benchmark failed: ${error instanceof Error ? error.message : String(error)}`);
  }
}

/**
 * Close the RuVector database connection
 */
export async function closeRuVector(): Promise<void> {
  if (db) {
    await db.close();
    db = null;
    console.log('RuVector connection closed');
  }
}
