/**
 * codeImporter.ts
 * 
 * Extracts code symbols (functions, classes, interfaces, etc.) from a TypeScript/JavaScript file.
 * Supports extracting multiple symbols and adjusting the heading level and text.
 */

import { readFileSync } from 'fs';

export interface CodeImportOptions {
  filePath: string;
  symbolList: string[];
  headingLevelOverride?: string;
  headingTextOverride?: string;
  skipHeading?: boolean;
}

export interface CodeImportResult {
  content: string;
  symbolsFound: boolean;
  duplicateSymbols: boolean;
}

export function importCodeSymbols(options: CodeImportOptions): CodeImportResult {
  const { filePath, symbolList, headingLevelOverride, headingTextOverride } = options;

  try {
    const content = readFileSync(filePath, 'utf-8');
    const lines = content.split('\n');
    const result: CodeImportResult = {
      content: '',
      symbolsFound: false,
      duplicateSymbols: false
    };

    // Track found symbols and their locations
    const foundSymbols = new Map<string, number[]>();
    let inComment = false;
    let inString = false;
    let stringChar = '';

    // Find all symbol locations
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i].trim();

      // Skip empty lines
      if (!line) continue;

      // Handle multi-line comments
      if (line.includes('/*')) inComment = true;
      if (line.includes('*/')) inComment = false;

      // Handle strings
      if (!inComment) {
        for (let j = 0; j < line.length; j++) {
          const char = line[j];
          if (inString) {
            if (char === stringChar && line[j - 1] !== '\\') {
              inString = false;
            }
          } else if (char === '"' || char === "'") {
            inString = true;
            stringChar = char;
          }
        }
      }

      // Skip comments and strings
      if (inComment || inString) continue;

      // Look for symbol declarations
      for (const symbol of symbolList) {
        if (line.includes(symbol)) {
          const locations = foundSymbols.get(symbol) || [];
          locations.push(i);
          foundSymbols.set(symbol, locations);
        }
      }
    }

    // Check for duplicates and missing symbols
    result.symbolsFound = symbolList.every(symbol => foundSymbols.has(symbol));
    result.duplicateSymbols = Array.from(foundSymbols.values()).some(locations => locations.length > 1);

    if (!result.symbolsFound || result.duplicateSymbols) {
      return result;
    }

    // Extract symbols
    const extractedContent: string[] = [];

    // Add heading by default unless skipHeading is true
    if (!options.skipHeading) {
      const heading = headingLevelOverride ?? '#';
      const text = headingTextOverride ?? 'Code Symbols';
      extractedContent.push(`${heading} ${text}`);
      extractedContent.push('');
    }

    // Add code fence
    extractedContent.push('```typescript');

    // Add each symbol's code
    for (const symbol of symbolList) {
      const locations = foundSymbols.get(symbol)!;
      const location = locations[0];
      let start = location;
      let end = location;

      // Find the start of the symbol (include JSDoc comments)
      while (start > 0 && (lines[start - 1].trim().startsWith('*') || lines[start - 1].trim().startsWith('/'))) {
        start--;
      }

      // Find the end of the symbol (include the entire block)
      let braceCount = 0;
      let foundFirstBrace = false;
      for (let i = location; i < lines.length; i++) {
        const line = lines[i];
        for (const char of line) {
          if (char === '{') {
            foundFirstBrace = true;
            braceCount++;
          } else if (char === '}') {
            braceCount--;
          }
        }
        end = i;
        if (foundFirstBrace && braceCount === 0) break;
        if (!foundFirstBrace && (line.trim().endsWith(';') || line.trim().endsWith('}'))) {
          break;
        }
      }

      // Add the symbol's code
      for (let i = start; i <= end; i++) {
        const line = lines[i];
        if (i === end && symbol === symbolList[symbolList.length - 1]) {
          const trimmedLine = line.trimEnd();
          if (trimmedLine.endsWith(';') || trimmedLine.endsWith('}')) {
            extractedContent.push(trimmedLine);
            extractedContent.push('```');
          } else {
            extractedContent.push(trimmedLine);
            extractedContent.push('```');
          }
        } else {
          extractedContent.push(line);
        }
      }

      // Add newline between symbols
      if (symbol !== symbolList[symbolList.length - 1]) {
        extractedContent.push('');
      }
    }

    result.content = extractedContent.join('\n');
    return result;
  } catch (error) {
    if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
      throw new Error('File not found');
    }
    throw error;
  }
} 