import { JSONSchema7 } from 'json-schema';
import { randomUUID } from 'crypto';
import { createTool, createSuccessResult, createErrorResult } from '../../core/tool-framework.js';
import { ToolRegistration, RequestContext } from '../../core/types.js';
import { promises as fs } from 'fs';
import path from 'path';

/**
 * Local AI Tools - 12-Factor MCP Implementation
 * 
 * Implements Factor 2: Deterministic Execution with structured outputs
 * Implements Factor 3: Stateless Processes with RequestContext
 * Implements Factor 4: Structured Outputs for LLM consumption
 * Implements Factor 5: Contextual Memory with SQLite persistence
 */

// Input type interfaces
interface IndexCodebaseInput {
  directory?: string;
  extensions?: string[];
  recursive?: boolean;
  includePatterns?: string[];
  excludePatterns?: string[];
}

interface SemanticSearchInput {
  query: string;
  topK?: number;
  threshold?: number;
  filters?: Record<string, any>;
}

interface FindSimilarCodeInput {
  filePath: string;
  topK?: number;
  threshold?: number;
}

interface AnalyzeDependenciesInput {
  file: string;
  depth?: number;
  includeTransitive?: boolean;
}

interface TrackCodeChangeInput {
  file: string;
  changeType: 'create' | 'modify' | 'delete';
  content?: string;
  metadata?: Record<string, any>;
}

interface AddCodeEmbeddingInput {
  filePath: string;
  content: string;
  language: string;
  metadata?: Record<string, any>;
}

interface SearchCodePatternsInput {
  patterns: string[];
  directory?: string;
  language?: string;
  includeMetadata?: boolean;
}

interface GetEmbeddingStatsInput {
  includeDetails?: boolean;
}

/**
 * Index codebase for semantic search and dependency analysis
 */
const indexCodebaseTool = createTool<IndexCodebaseInput, any>({
  name: 'index_codebase',
  description: 'Index codebase for semantic search and dependency analysis with SQLite storage',
  category: 'local-ai',
  inputSchema: {
    type: 'object',
    properties: {
      directory: {
        type: 'string',
        default: '.',
        description: 'Directory to index (relative or absolute path)',
        maxLength: 500
      },
      extensions: {
        type: 'array',
        items: { type: 'string', maxLength: 10 },
        default: ['.ts', '.js', '.tsx', '.jsx', '.py', '.rs', '.go'],
        description: 'File extensions to include',
        maxItems: 20
      },
      recursive: {
        type: 'boolean',
        default: true,
        description: 'Recursively index subdirectories'
      },
      includePatterns: {
        type: 'array',
        items: { type: 'string', maxLength: 100 },
        description: 'Glob patterns to include',
        maxItems: 10
      },
      excludePatterns: {
        type: 'array',
        items: { type: 'string', maxLength: 100 },
        default: ['node_modules/**', '.git/**', 'dist/**', 'build/**'],
        description: 'Glob patterns to exclude',
        maxItems: 20
      }
    },
    additionalProperties: false
  } as JSONSchema7,

  async execute(input: IndexCodebaseInput, context: RequestContext) {
    try {
      const indexId = randomUUID();
      const now = Date.now();

      // Resolve directory path
      const dir = path.isAbsolute(input.directory || '.')
        ? input.directory || '.'
        : path.join(process.cwd(), input.directory || '.');

      // Find code files
      const files = await findCodeFiles(dir, {
        extensions: input.extensions || ['.ts', '.js', '.tsx', '.jsx', '.py', '.rs', '.go'],
        recursive: input.recursive !== false,
        includePatterns: input.includePatterns || [],
        excludePatterns: input.excludePatterns || ['node_modules/**', '.git/**', 'dist/**', 'build/**']
      });

      let indexed = 0;
      let failed = 0;
      const errors: string[] = [];

      // Process files and store embeddings
      for (const file of files) {
        try {
          const content = await fs.readFile(file, 'utf-8');
          const language = detectLanguage(file);
          const relativePath = path.relative(dir, file);

          // Extract code features
          const features = extractCodeFeatures(content, language);
          const functions = extractFunctions(content, language);
          const imports = extractImports(content, language);

          // Generate embedding data
          const embeddingData = generateEmbeddingData(content, language, features);

          // Store in database
          const result = await context.db.run(
            `INSERT INTO ai_embeddings 
             (id, project_id, file_path, content, language, features, functions, imports, 
              embedding_data, file_size, last_modified, created_at, updated_at) 
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
            [
              randomUUID(),
              context.projectId || 'default',
              relativePath,
              content,
              language,
              JSON.stringify(features),
              JSON.stringify(functions),
              JSON.stringify(imports),
              JSON.stringify(embeddingData),
              content.length,
              now,
              now,
              now
            ]
          );

          if (result.success) {
            indexed++;
          } else {
            failed++;
            errors.push(`Failed to store ${relativePath}: ${result.error}`);
          }
        } catch (error) {
          failed++;
          errors.push(`Error processing ${file}: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
      }

      // Store indexing session
      await context.db.run(
        `INSERT INTO ai_indexing_sessions 
         (id, project_id, directory, files_found, files_indexed, files_failed, 
          extensions, errors, created_at) 
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [
          indexId,
          context.projectId || 'default',
          dir,
          files.length,
          indexed,
          failed,
          JSON.stringify(input.extensions),
          JSON.stringify(errors.slice(0, 100)), // Limit error storage
          now
        ]
      );

      return createSuccessResult({
        indexingSession: {
          id: indexId,
          directory: dir,
          filesFound: files.length,
          filesIndexed: indexed,
          filesFailed: failed,
          embeddingCount: indexed,
          errors: errors.slice(0, 10) // Limit errors in response
        },
        message: `Successfully indexed ${indexed}/${files.length} files for semantic search`,
        summary: {
          total: files.length,
          indexed,
          failed,
          successRate: files.length > 0 ? (indexed / files.length) * 100 : 0
        }
      });

    } catch (error) {
      return createErrorResult({
        code: 'EXECUTION_ERROR',
        message: `Failed to index codebase: ${error instanceof Error ? error.message : 'Unknown error'}`,
        category: 'execution'
      });
    }
  }
});

/**
 * Search codebase using semantic search
 */
const semanticSearchTool = createTool<SemanticSearchInput, any>({
  name: 'semantic_search',
  description: 'Search codebase using natural language queries with semantic similarity',
  category: 'local-ai',
  readOnly: true,
  inputSchema: {
    type: 'object',
    properties: {
      query: {
        type: 'string',
        description: 'Natural language search query',
        minLength: 1,
        maxLength: 500
      },
      topK: {
        type: 'number',
        default: 5,
        description: 'Number of results to return',
        minimum: 1,
        maximum: 50
      },
      threshold: {
        type: 'number',
        default: 0.3,
        description: 'Minimum similarity threshold (0-1)',
        minimum: 0,
        maximum: 1
      },
      filters: {
        type: 'object',
        description: 'Additional filters (language, file patterns, etc.)',
        additionalProperties: true
      }
    },
    required: ['query'],
    additionalProperties: false
  } as JSONSchema7,

  async execute(input: SemanticSearchInput, context: RequestContext) {
    try {
      const searchId = randomUUID();
      const now = Date.now();

      // Generate query embedding
      const queryEmbedding = generateQueryEmbedding(input.query);

      // Build search query with filters
      let sqlQuery = `
        SELECT id, file_path, content, language, features, functions, imports, 
               embedding_data, file_size, created_at
        FROM ai_embeddings 
        WHERE project_id = ?
      `;
      const params: any[] = [context.projectId || 'default'];

      // Apply filters
      if (input.filters?.language) {
        sqlQuery += ' AND language = ?';
        params.push(input.filters.language);
      }

      if (input.filters?.filePattern) {
        sqlQuery += ' AND file_path LIKE ?';
        params.push(`%${input.filters.filePattern}%`);
      }

      sqlQuery += ' ORDER BY created_at DESC LIMIT ?';
      params.push(input.topK || 5);

      const embeddings = await context.db.all(sqlQuery, params);

      if (!embeddings.success || !embeddings.data) {
        return createSuccessResult({
          query: input.query,
          results: [],
          message: 'No embeddings found. Try indexing the codebase first with index_codebase'
        });
      }

      // Calculate similarity scores
      const results = embeddings.data
        .map((row: any) => {
          const embeddingData = JSON.parse(row.embedding_data);
          const similarity = calculateSimilarity(queryEmbedding, embeddingData);
          
          return {
            id: row.id,
            filePath: row.file_path,
            language: row.language,
            similarity,
            features: JSON.parse(row.features || '[]'),
            functions: JSON.parse(row.functions || '[]'),
            imports: JSON.parse(row.imports || '[]'),
            fileSize: row.file_size,
            preview: generatePreview(row.content, input.query),
            metadata: {
              createdAt: row.created_at,
              language: row.language
            }
          };
        })
        .filter((result: any) => result.similarity >= (input.threshold || 0.3))
        .sort((a: any, b: any) => b.similarity - a.similarity)
        .slice(0, input.topK || 5);

      // Store search session
      await context.db.run(
        `INSERT INTO ai_search_sessions 
         (id, project_id, query, results_found, top_similarity, filters, created_at) 
         VALUES (?, ?, ?, ?, ?, ?, ?)`,
        [
          searchId,
          context.projectId || 'default',
          input.query,
          results.length,
          results.length > 0 ? results[0].similarity : 0,
          JSON.stringify(input.filters || {}),
          now
        ]
      );

      return createSuccessResult({
        searchSession: {
          id: searchId,
          query: input.query,
          resultsFound: results.length,
          threshold: input.threshold || 0.3
        },
        results,
        message: results.length > 0 
          ? `Found ${results.length} relevant code files` 
          : 'No matching code found for your query',
        summary: {
          totalResults: results.length,
          avgSimilarity: results.length > 0 
            ? results.reduce((sum: number, r: any) => sum + r.similarity, 0) / results.length 
            : 0,
          languages: [...new Set(results.map((r: any) => r.language))]
        }
      });

    } catch (error) {
      return createErrorResult({
        code: 'EXECUTION_ERROR',
        message: `Failed to perform semantic search: ${error instanceof Error ? error.message : 'Unknown error'}`,
        category: 'execution'
      });
    }
  }
});

/**
 * Find files with similar code patterns
 */
const findSimilarCodeTool = createTool<FindSimilarCodeInput, any>({
  name: 'find_similar_code',
  description: 'Find files with similar code patterns to a given file',
  category: 'local-ai',
  readOnly: true,
  inputSchema: {
    type: 'object',
    properties: {
      filePath: {
        type: 'string',
        description: 'Path to file to find similar code for',
        minLength: 1,
        maxLength: 500
      },
      topK: {
        type: 'number',
        default: 5,
        description: 'Number of similar files to return',
        minimum: 1,
        maximum: 20
      },
      threshold: {
        type: 'number',
        default: 0.5,
        description: 'Minimum similarity threshold (0-1)',
        minimum: 0,
        maximum: 1
      }
    },
    required: ['filePath'],
    additionalProperties: false
  } as JSONSchema7,

  async execute(input: FindSimilarCodeInput, context: RequestContext) {
    try {
      // Get the target file's embedding
      const targetFile = await context.db.get(
        'SELECT * FROM ai_embeddings WHERE project_id = ? AND file_path = ?',
        [context.projectId || 'default', input.filePath]
      );

      if (!targetFile.success || !targetFile.data) {
        return createErrorResult({
          code: 'NOT_FOUND',
          message: `File ${input.filePath} not found in embeddings. Try indexing it first.`,
          category: 'validation'
        });
      }

      const targetEmbedding = JSON.parse(targetFile.data.embedding_data);

      // Get all other embeddings
      const allEmbeddings = await context.db.all(
        'SELECT * FROM ai_embeddings WHERE project_id = ? AND file_path != ?',
        [context.projectId || 'default', input.filePath]
      );

      if (!allEmbeddings.success || !allEmbeddings.data) {
        return createSuccessResult({
          sourceFile: input.filePath,
          similarFiles: [],
          message: 'No other files found in the index'
        });
      }

      // Calculate similarities
      const similarities = allEmbeddings.data
        .map((row: any) => {
          const embedding = JSON.parse(row.embedding_data);
          const similarity = calculateSimilarity(targetEmbedding, embedding);
          
          return {
            filePath: row.file_path,
            language: row.language,
            similarity,
            features: JSON.parse(row.features || '[]'),
            functions: JSON.parse(row.functions || '[]'),
            sharedFeatures: findSharedFeatures(
              JSON.parse(targetFile.data.features || '[]'),
              JSON.parse(row.features || '[]')
            ),
            fileSize: row.file_size
          };
        })
        .filter((result: any) => result.similarity >= (input.threshold || 0.5))
        .sort((a: any, b: any) => b.similarity - a.similarity)
        .slice(0, input.topK || 5);

      return createSuccessResult({
        sourceFile: input.filePath,
        sourceLanguage: targetFile.data.language,
        similarFiles: similarities,
        message: similarities.length > 0 
          ? `Found ${similarities.length} similar files` 
          : 'No similar files found',
        analysis: {
          totalCandidates: allEmbeddings.data.length,
          belowThreshold: allEmbeddings.data.length - similarities.length,
          averageSimilarity: similarities.length > 0 
            ? similarities.reduce((sum: number, s: any) => sum + s.similarity, 0) / similarities.length 
            : 0
        }
      });

    } catch (error) {
      return createErrorResult({
        code: 'EXECUTION_ERROR',
        message: `Failed to find similar code: ${error instanceof Error ? error.message : 'Unknown error'}`,
        category: 'execution'
      });
    }
  }
});

/**
 * Analyze code dependencies and relationships
 */
const analyzeDependenciesTool = createTool<AnalyzeDependenciesInput, any>({
  name: 'analyze_dependencies',
  description: 'Analyze code dependencies and relationships',
  category: 'local-ai',
  readOnly: true,
  inputSchema: {
    type: 'object',
    properties: {
      file: {
        type: 'string',
        description: 'File to analyze dependencies for',
        minLength: 1,
        maxLength: 500
      },
      depth: {
        type: 'number',
        default: 2,
        description: 'Depth of dependency analysis',
        minimum: 1,
        maximum: 5
      },
      includeTransitive: {
        type: 'boolean',
        default: true,
        description: 'Include transitive dependencies'
      }
    },
    required: ['file'],
    additionalProperties: false
  } as JSONSchema7,

  async execute(input: AnalyzeDependenciesInput, context: RequestContext) {
    try {
      const analysisId = randomUUID();
      const now = Date.now();

      // Get file's dependencies
      const fileData = await context.db.get(
        'SELECT * FROM ai_embeddings WHERE project_id = ? AND file_path = ?',
        [context.projectId || 'default', input.file]
      );

      if (!fileData.success || !fileData.data) {
        return createErrorResult({
          code: 'NOT_FOUND',
          message: `File ${input.file} not found in embeddings`,
          category: 'validation'
        });
      }

      const imports = JSON.parse(fileData.data.imports || '[]');
      const functions = JSON.parse(fileData.data.functions || '[]');

      // Analyze dependency relationships
      const dependencyAnalysis = await analyzeDependencyRelationships(
        context,
        input.file,
        imports,
        input.depth || 2,
        input.includeTransitive !== false
      );

      // Store analysis
      await context.db.run(
        `INSERT INTO ai_dependency_analyses 
         (id, project_id, target_file, depth, dependencies, circular_deps, 
          hotspots, analysis_data, created_at) 
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [
          analysisId,
          context.projectId || 'default',
          input.file,
          input.depth || 2,
          JSON.stringify(dependencyAnalysis.dependencies),
          JSON.stringify(dependencyAnalysis.circularDependencies),
          JSON.stringify(dependencyAnalysis.hotspots),
          JSON.stringify(dependencyAnalysis),
          now
        ]
      );

      return createSuccessResult({
        analysis: {
          id: analysisId,
          targetFile: input.file,
          dependencies: dependencyAnalysis.dependencies,
          circularDependencies: dependencyAnalysis.circularDependencies,
          hotspots: dependencyAnalysis.hotspots,
          metrics: dependencyAnalysis.metrics
        },
        message: `Analyzed dependencies for ${input.file}`,
        insights: {
          totalDependencies: dependencyAnalysis.dependencies.length,
          circularCount: dependencyAnalysis.circularDependencies.length,
          complexityScore: dependencyAnalysis.metrics.complexityScore,
          recommendations: dependencyAnalysis.recommendations
        }
      });

    } catch (error) {
      return createErrorResult({
        code: 'EXECUTION_ERROR',
        message: `Failed to analyze dependencies: ${error instanceof Error ? error.message : 'Unknown error'}`,
        category: 'execution'
      });
    }
  }
});

/**
 * Track code changes in the semantic index
 */
const trackCodeChangeTool = createTool<TrackCodeChangeInput, any>({
  name: 'track_code_change',
  description: 'Track code changes in memory for pattern analysis and semantic search',
  category: 'local-ai',
  inputSchema: {
    type: 'object',
    properties: {
      file: {
        type: 'string',
        description: 'File that changed',
        minLength: 1,
        maxLength: 500
      },
      changeType: {
        type: 'string',
        enum: ['create', 'modify', 'delete'],
        description: 'Type of change'
      },
      content: {
        type: 'string',
        description: 'New content (required for create/modify)',
        maxLength: 1000000
      },
      metadata: {
        type: 'object',
        description: 'Additional metadata about the change',
        additionalProperties: true
      }
    },
    required: ['file', 'changeType'],
    additionalProperties: false
  } as JSONSchema7,

  async execute(input: TrackCodeChangeInput, context: RequestContext) {
    try {
      const changeId = randomUUID();
      const now = Date.now();

      if (input.changeType === 'delete') {
        // Remove from embeddings
        await context.db.run(
          'DELETE FROM ai_embeddings WHERE project_id = ? AND file_path = ?',
          [context.projectId || 'default', input.file]
        );
        
        // Record the deletion
        await context.db.run(
          `INSERT INTO ai_code_changes 
           (id, project_id, file_path, change_type, metadata, created_at) 
           VALUES (?, ?, ?, ?, ?, ?)`,
          [
            changeId,
            context.projectId || 'default',
            input.file,
            input.changeType,
            JSON.stringify(input.metadata || {}),
            now
          ]
        );

        return createSuccessResult({
          changeId,
          action: 'deleted',
          file: input.file,
          message: `Removed ${input.file} from semantic index`
        });
      }

      if (!input.content) {
        return createErrorResult({
          code: 'VALIDATION_ERROR',
          message: 'Content is required for create/modify operations',
          category: 'validation'
        });
      }

      const language = detectLanguage(input.file);
      const features = extractCodeFeatures(input.content, language);
      const functions = extractFunctions(input.content, language);
      const imports = extractImports(input.content, language);
      const embeddingData = generateEmbeddingData(input.content, language, features);

      // Update or insert embedding
      const existingResult = await context.db.get(
        'SELECT id FROM ai_embeddings WHERE project_id = ? AND file_path = ?',
        [context.projectId || 'default', input.file]
      );

      if (existingResult.success && existingResult.data) {
        // Update existing
        await context.db.run(
          `UPDATE ai_embeddings 
           SET content = ?, language = ?, features = ?, functions = ?, imports = ?, 
               embedding_data = ?, file_size = ?, last_modified = ?, updated_at = ?
           WHERE project_id = ? AND file_path = ?`,
          [
            input.content,
            language,
            JSON.stringify(features),
            JSON.stringify(functions),
            JSON.stringify(imports),
            JSON.stringify(embeddingData),
            input.content.length,
            now,
            now,
            context.projectId || 'default',
            input.file
          ]
        );
      } else {
        // Insert new
        await context.db.run(
          `INSERT INTO ai_embeddings 
           (id, project_id, file_path, content, language, features, functions, imports, 
            embedding_data, file_size, last_modified, created_at, updated_at) 
           VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
          [
            randomUUID(),
            context.projectId || 'default',
            input.file,
            input.content,
            language,
            JSON.stringify(features),
            JSON.stringify(functions),
            JSON.stringify(imports),
            JSON.stringify(embeddingData),
            input.content.length,
            now,
            now,
            now
          ]
        );
      }

      // Record the change
      await context.db.run(
        `INSERT INTO ai_code_changes 
         (id, project_id, file_path, change_type, language, features_added, 
          functions_added, metadata, created_at) 
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [
          changeId,
          context.projectId || 'default',
          input.file,
          input.changeType,
          language,
          JSON.stringify(features),
          JSON.stringify(functions),
          JSON.stringify(input.metadata || {}),
          now
        ]
      );

      return createSuccessResult({
        changeId,
        action: input.changeType === 'create' ? 'indexed' : 'updated',
        file: input.file,
        language,
        metrics: {
          featuresExtracted: features.length,
          functionsFound: functions.length,
          importsFound: imports.length,
          fileSize: input.content.length
        },
        message: `Successfully ${input.changeType === 'create' ? 'indexed' : 'updated'} ${input.file} in semantic search`
      });

    } catch (error) {
      return createErrorResult({
        code: 'EXECUTION_ERROR',
        message: `Failed to track code change: ${error instanceof Error ? error.message : 'Unknown error'}`,
        category: 'execution'
      });
    }
  }
});

/**
 * Get embedding statistics and health metrics
 */
const getEmbeddingStatsTool = createTool<GetEmbeddingStatsInput, any>({
  name: 'get_embedding_stats',
  description: 'Get statistics about the current embedding index',
  category: 'local-ai',
  readOnly: true,
  inputSchema: {
    type: 'object',
    properties: {
      includeDetails: {
        type: 'boolean',
        default: false,
        description: 'Include detailed breakdown by language and features'
      }
    },
    additionalProperties: false
  } as JSONSchema7,

  async execute(input: GetEmbeddingStatsInput, context: RequestContext) {
    try {
      // Get basic statistics
      const totalCount = await context.db.get(
        'SELECT COUNT(*) as count FROM ai_embeddings WHERE project_id = ?',
        [context.projectId || 'default']
      );

      const languageStats = await context.db.all(
        'SELECT language, COUNT(*) as count FROM ai_embeddings WHERE project_id = ? GROUP BY language',
        [context.projectId || 'default']
      );

      const indexingStats = await context.db.get(
        `SELECT COUNT(*) as sessions, 
         SUM(files_indexed) as total_indexed, 
         AVG(files_indexed) as avg_per_session
         FROM ai_indexing_sessions WHERE project_id = ?`,
        [context.projectId || 'default']
      );

      const searchStats = await context.db.get(
        `SELECT COUNT(*) as searches,
         AVG(results_found) as avg_results,
         AVG(top_similarity) as avg_similarity
         FROM ai_search_sessions WHERE project_id = ?`,
        [context.projectId || 'default']
      );

      const recentActivity = await context.db.all(
        `SELECT change_type, COUNT(*) as count 
         FROM ai_code_changes 
         WHERE project_id = ? AND created_at > ?
         GROUP BY change_type`,
        [context.projectId || 'default', Date.now() - (7 * 24 * 60 * 60 * 1000)] // Last 7 days
      );

      const stats = {
        totalEmbeddings: totalCount.data?.count || 0,
        languageBreakdown: languageStats.data || [],
        indexingSessions: indexingStats.data?.sessions || 0,
        totalFilesIndexed: indexingStats.data?.total_indexed || 0,
        averageFilesPerSession: indexingStats.data?.avg_per_session || 0,
        searchSessions: searchStats.data?.searches || 0,
        averageResultsPerSearch: searchStats.data?.avg_results || 0,
        averageSearchSimilarity: searchStats.data?.avg_similarity || 0,
        recentActivity: recentActivity.data || []
      };

      let details = {};
      if (input.includeDetails) {
        // Get additional detailed statistics
        const featureStats = await context.db.all(
          `SELECT language, 
           AVG(JSON_ARRAY_LENGTH(features)) as avg_features,
           AVG(JSON_ARRAY_LENGTH(functions)) as avg_functions,
           AVG(file_size) as avg_file_size
           FROM ai_embeddings 
           WHERE project_id = ? 
           GROUP BY language`,
          [context.projectId || 'default']
        );

        const topFiles = await context.db.all(
          `SELECT file_path, language, file_size, 
           JSON_ARRAY_LENGTH(features) as feature_count,
           JSON_ARRAY_LENGTH(functions) as function_count
           FROM ai_embeddings 
           WHERE project_id = ? 
           ORDER BY file_size DESC 
           LIMIT 10`,
          [context.projectId || 'default']
        );

        details = {
          featureStatsByLanguage: featureStats.data || [],
          largestFiles: topFiles.data || []
        };
      }

      return createSuccessResult({
        statistics: stats,
        details: input.includeDetails ? details : undefined,
        healthMetrics: {
          indexingHealth: stats.totalEmbeddings > 0 ? 'good' : 'needs_indexing',
          searchUsage: stats.searchSessions > 0 ? 'active' : 'unused',
          diversityScore: stats.languageBreakdown.length,
          lastActivity: recentActivity.data && recentActivity.data.length > 0 ? 'recent' : 'stale'
        },
        message: `Index contains ${stats.totalEmbeddings} embeddings across ${stats.languageBreakdown.length} languages`
      });

    } catch (error) {
      return createErrorResult({
        code: 'EXECUTION_ERROR',
        message: `Failed to get embedding stats: ${error instanceof Error ? error.message : 'Unknown error'}`,
        category: 'execution'
      });
    }
  }
});

// Helper functions

async function findCodeFiles(
  dir: string, 
  options: { extensions: string[], recursive: boolean, includePatterns: string[], excludePatterns: string[] }
): Promise<string[]> {
  const files: string[] = [];
  
  async function walk(currentDir: string) {
    try {
      const entries = await fs.readdir(currentDir, { withFileTypes: true });
      
      for (const entry of entries) {
        const fullPath = path.join(currentDir, entry.name);
        
        // Check exclude patterns
        const relativePath = path.relative(dir, fullPath);
        if (options.excludePatterns.some(pattern => 
          relativePath.includes(pattern.replace('/**', '')) || 
          entry.name.startsWith('.')
        )) {
          continue;
        }
        
        if (entry.isDirectory() && options.recursive) {
          await walk(fullPath);
        } else if (entry.isFile() && options.extensions.some(ext => entry.name.endsWith(ext))) {
          files.push(fullPath);
        }
      }
    } catch (error) {
      // Skip directories we can't read
    }
  }
  
  await walk(dir);
  return files;
}

function detectLanguage(filePath: string): string {
  const ext = path.extname(filePath).toLowerCase();
  const languageMap: Record<string, string> = {
    '.ts': 'typescript',
    '.tsx': 'typescript',
    '.js': 'javascript',
    '.jsx': 'javascript',
    '.py': 'python',
    '.rs': 'rust',
    '.go': 'go',
    '.java': 'java',
    '.cpp': 'cpp',
    '.c': 'c',
    '.h': 'c',
    '.hpp': 'cpp',
    '.cs': 'csharp',
    '.php': 'php',
    '.rb': 'ruby',
    '.swift': 'swift',
    '.kt': 'kotlin',
    '.scala': 'scala',
    '.clj': 'clojure'
  };
  
  return languageMap[ext] || 'unknown';
}

function extractCodeFeatures(content: string, language: string): string[] {
  const features: string[] = [];
  
  // Extract based on language
  if (language === 'typescript' || language === 'javascript') {
    // Classes
    const classMatches = content.match(/(?:class|interface)\s+(\w+)/g);
    if (classMatches) {
      classMatches.forEach(match => {
        const name = match.split(/\s+/)[1];
        features.push(`class:${name}`);
      });
    }
    
    // Types and interfaces
    const typeMatches = content.match(/(?:type|interface)\s+(\w+)/g);
    if (typeMatches) {
      typeMatches.forEach(match => {
        const name = match.split(/\s+/)[1];
        features.push(`type:${name}`);
      });
    }
    
    // Async functions
    if (content.includes('async ')) {
      features.push('pattern:async');
    }
    
    // React patterns
    if (content.includes('useState') || content.includes('useEffect')) {
      features.push('pattern:react-hooks');
    }
    
    // Error handling
    if (content.includes('try') && content.includes('catch')) {
      features.push('pattern:error-handling');
    }
  }
  
  // Common patterns across languages
  if (content.includes('test') || content.includes('spec')) {
    features.push('pattern:testing');
  }
  
  if (content.includes('API') || content.includes('endpoint')) {
    features.push('pattern:api');
  }
  
  if (content.includes('database') || content.includes('SQL') || content.includes('query')) {
    features.push('pattern:database');
  }
  
  return features;
}

function extractFunctions(content: string, language: string): string[] {
  const functions: string[] = [];
  
  if (language === 'typescript' || language === 'javascript') {
    // Function declarations and expressions
    const functionRegex = /(?:function\s+(\w+)|(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?(?:function|\([^)]*\)\s*=>))/g;
    let match;
    while ((match = functionRegex.exec(content)) !== null) {
      const name = match[1] || match[2];
      if (name) functions.push(name);
    }
    
    // Method definitions
    const methodRegex = /(\w+)\s*\([^)]*\)\s*{/g;
    while ((match = methodRegex.exec(content)) !== null) {
      if (!functions.includes(match[1])) {
        functions.push(match[1]);
      }
    }
  } else if (language === 'python') {
    const funcRegex = /def\s+(\w+)\s*\(/g;
    let match;
    while ((match = funcRegex.exec(content)) !== null) {
      functions.push(match[1]);
    }
  }
  
  return functions;
}

function extractImports(content: string, language: string): string[] {
  const imports: string[] = [];
  
  if (language === 'typescript' || language === 'javascript') {
    const importRegex = /import\s+.*\s+from\s+['"]([^'"]+)['"]/g;
    let match;
    while ((match = importRegex.exec(content)) !== null) {
      imports.push(match[1]);
    }
    
    const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
    while ((match = requireRegex.exec(content)) !== null) {
      imports.push(match[1]);
    }
  } else if (language === 'python') {
    const importRegex = /(?:import\s+(\w+)|from\s+(\w+)\s+import)/g;
    let match;
    while ((match = importRegex.exec(content)) !== null) {
      imports.push(match[1] || match[2]);
    }
  }
  
  return imports;
}

function generateEmbeddingData(content: string, language: string, features: string[]): any {
  // Simple hash-based embedding for local use
  // In production, this would use a proper embedding model
  const text = `${language} ${features.join(' ')} ${content}`;
  const hash = require('crypto').createHash('sha256').update(text).digest('hex');
  
  // Generate a simple vector representation
  const vector = [];
  for (let i = 0; i < 128; i++) {
    const byte = parseInt(hash.substr(i % hash.length, 2), 16);
    vector.push((byte / 255.0) * 2 - 1); // Normalize to [-1, 1]
  }
  
  return {
    vector,
    textHash: hash,
    dimensions: 128,
    model: 'local-hash-embedding'
  };
}

function generateQueryEmbedding(query: string): any {
  return generateEmbeddingData(query, 'query', []);
}

function calculateSimilarity(embedding1: any, embedding2: any): number {
  if (!embedding1.vector || !embedding2.vector) return 0;
  
  const v1 = embedding1.vector;
  const v2 = embedding2.vector;
  
  if (v1.length !== v2.length) return 0;
  
  // Cosine similarity
  let dotProduct = 0;
  let norm1 = 0;
  let norm2 = 0;
  
  for (let i = 0; i < v1.length; i++) {
    dotProduct += v1[i] * v2[i];
    norm1 += v1[i] * v1[i];
    norm2 += v2[i] * v2[i];
  }
  
  if (norm1 === 0 || norm2 === 0) return 0;
  
  return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
}

function generatePreview(content: string, query: string): string {
  const lines = content.split('\n');
  const queryWords = query.toLowerCase().split(/\s+/);
  
  // Find lines that contain query words
  const relevantLines: { line: string, index: number, score: number }[] = [];
  
  lines.forEach((line, index) => {
    const lowerLine = line.toLowerCase();
    const score = queryWords.reduce((acc, word) => {
      return acc + (lowerLine.includes(word) ? 1 : 0);
    }, 0);
    
    if (score > 0) {
      relevantLines.push({ line: line.trim(), index, score });
    }
  });
  
  // Sort by score and take top 3 lines
  const topLines = relevantLines
    .sort((a, b) => b.score - a.score)
    .slice(0, 3)
    .map(item => `Line ${item.index + 1}: ${item.line}`)
    .join('\n');
    
  return topLines || lines.slice(0, 3).join('\n');
}

function findSharedFeatures(features1: string[], features2: string[]): string[] {
  return features1.filter(f => features2.includes(f));
}

async function analyzeDependencyRelationships(
  context: RequestContext,
  targetFile: string,
  imports: string[],
  depth: number,
  includeTransitive: boolean
): Promise<any> {
  // This is a simplified implementation
  // In practice, this would do deeper analysis of the dependency graph
  
  const dependencies: string[] = [];
  const circularDependencies: string[] = [];
  const hotspots: string[] = [];
  
  // Analyze direct dependencies
  for (const imp of imports) {
    // Find files that might correspond to this import
    const possibleFiles = await context.db.all(
      `SELECT file_path FROM ai_embeddings 
       WHERE project_id = ? AND file_path LIKE ?`,
      [context.projectId || 'default', `%${imp}%`]
    );
    
    if (possibleFiles.success && possibleFiles.data) {
      dependencies.push(...possibleFiles.data.map((f: any) => f.file_path));
    }
  }
  
  // Simple metrics calculation
  const metrics = {
    directDependencies: dependencies.length,
    totalDependencies: dependencies.length, // Would include transitive in full implementation
    complexityScore: Math.min(dependencies.length * 10, 100),
    fanOut: dependencies.length,
    fanIn: 0 // Would calculate reverse dependencies
  };
  
  const recommendations = [];
  if (metrics.complexityScore > 70) {
    recommendations.push('Consider breaking down this file to reduce complexity');
  }
  if (dependencies.length > 10) {
    recommendations.push('High number of dependencies - consider dependency injection');
  }
  
  return {
    dependencies,
    circularDependencies,
    hotspots,
    metrics,
    recommendations
  };
}

/**
 * Setup local AI tools
 */
export async function setupLocalAITools(): Promise<ToolRegistration> {
  return {
    module: 'local-ai',
    tools: [
      indexCodebaseTool,
      semanticSearchTool,
      findSimilarCodeTool,
      analyzeDependenciesTool,
      trackCodeChangeTool,
      getEmbeddingStatsTool
    ]
  };
}