import { logger } from '../utils/logger';
import { vectorDatabaseService } from './vectorDatabaseService';
import { VectorDatabaseModel } from '../models/VectorDatabaseModel';
import { llmService } from './llmService';
import { CIMReview } from './llmSchemas';

interface ProcessingChunk {
  id: string;
  content: string;
  chunkIndex: number;
  startPosition: number;
  endPosition: number;
  sectionType?: string;
  metadata?: Record<string, any>;
}

interface ProcessingResult {
  totalChunks: number;
  processedChunks: number;
  processingTime: number;
  averageChunkSize: number;
  memoryUsage: number;
  summary?: string;
  analysisData?: CIMReview;
  success: boolean;
  error?: string;
}

export class OptimizedAgenticRAGProcessor {
  private readonly maxChunkSize = 4000; // Optimal chunk size for embeddings
  private readonly overlapSize = 200; // Overlap between chunks
  private readonly maxConcurrentEmbeddings = 5; // Limit concurrent API calls
  private readonly batchSize = 10; // Process chunks in batches

  /**
   * Process large documents with optimized memory usage and proper chunking
   */
  async processLargeDocument(
    documentId: string,
    text: string,
    options: {
      enableSemanticChunking?: boolean;
      enableMetadataEnrichment?: boolean;
      similarityThreshold?: number;
    } = {}
  ): Promise<ProcessingResult> {
    const startTime = Date.now();
    const initialMemory = process.memoryUsage().heapUsed;

    try {
      logger.info(`Starting optimized processing for document: ${documentId}`, {
        textLength: text.length,
        estimatedChunks: Math.ceil(text.length / this.maxChunkSize)
      });

      // Step 1: Create intelligent chunks with semantic boundaries
      const chunks = await this.createIntelligentChunks(text, documentId, options.enableSemanticChunking);

      // Step 2: Process chunks in batches to manage memory
      const processedChunks = await this.processChunksInBatches(chunks, documentId, options);

      // Step 3: Store chunks with optimized batching
      await this.storeChunksOptimized(processedChunks, documentId);

      // Step 4: Generate LLM analysis using the vectorized chunks
      logger.info(`Starting LLM analysis for document: ${documentId}`);
      const llmResult = await this.generateLLMAnalysis(documentId, text, processedChunks);

      const processingTime = Date.now() - startTime;
      const finalMemory = process.memoryUsage().heapUsed;
      const memoryUsage = finalMemory - initialMemory;

      const result: ProcessingResult = {
        totalChunks: chunks.length,
        processedChunks: processedChunks.length,
        processingTime,
        averageChunkSize: Math.round(processedChunks.reduce((sum: number, c: any) => sum + c.content.length, 0) / processedChunks.length),
        memoryUsage: Math.round(memoryUsage / 1024 / 1024), // MB
        success: true,
        summary: llmResult.summary,
        analysisData: llmResult.analysisData
      };

      logger.info(`Optimized processing completed for document: ${documentId}`, result);

      console.log('✅ Optimized agentic RAG processing completed successfully for document:', documentId);
      console.log('✅ Total chunks processed:', result.processedChunks);
      console.log('✅ Processing time:', result.processingTime, 'ms');
      console.log('✅ Memory usage:', result.memoryUsage, 'MB');
      console.log('✅ Summary length:', result.summary?.length || 0);

      return result;
    } catch (error) {
      logger.error(`Optimized processing failed for document: ${documentId}`, error);
      
      console.log('❌ Optimized agentic RAG processing failed for document:', documentId);
      console.log('❌ Error:', error instanceof Error ? error.message : String(error));
      
      throw error;
    }
  }

  /**
   * Create intelligent chunks with semantic boundaries
   */
  private async createIntelligentChunks(
    text: string,
    documentId: string,
    enableSemanticChunking: boolean = true
  ): Promise<ProcessingChunk[]> {
    const chunks: ProcessingChunk[] = [];

    if (enableSemanticChunking) {
      // Use semantic boundaries for better chunking
      const semanticChunks = this.splitBySemanticBoundaries(text);
      
      for (let i = 0; i < semanticChunks.length; i++) {
        const chunk = semanticChunks[i];
        if (chunk && chunk.content.length > 50) { // Skip tiny chunks
          chunks.push({
            id: `${documentId}-chunk-${i}`,
            content: chunk.content,
            chunkIndex: i,
            startPosition: chunk.startPosition,
            endPosition: chunk.endPosition,
            sectionType: chunk.sectionType || 'general',
            metadata: chunk.metadata || {}
          });
        }
      }
    } else {
      // Fallback to simple sliding window chunking
      for (let i = 0; i < text.length; i += this.maxChunkSize - this.overlapSize) {
        const chunkContent = text.substring(i, i + this.maxChunkSize);
        if (chunkContent.trim().length > 50) {
          chunks.push({
            id: `${documentId}-chunk-${chunks.length}`,
            content: chunkContent.trim(),
            chunkIndex: chunks.length,
            startPosition: i,
            endPosition: i + chunkContent.length
          });
        }
      }
    }

    logger.info(`Created ${chunks.length} chunks for document: ${documentId}`);
    return chunks;
  }

  /**
   * Split text by semantic boundaries (paragraphs, sections, etc.)
   */
  private splitBySemanticBoundaries(text: string): Array<{
    content: string;
    startPosition: number;
    endPosition: number;
    sectionType?: string;
    metadata?: Record<string, any>;
  }> {
    const chunks: Array<{
      content: string;
      startPosition: number;
      endPosition: number;
      sectionType?: string;
      metadata?: Record<string, any>;
    }> = [];

    // Split by double newlines (paragraphs)
    const paragraphs = text.split(/\n\s*\n/);
    let currentPosition = 0;

    for (const paragraph of paragraphs) {
      if (paragraph.trim().length === 0) {
        currentPosition += paragraph.length + 2; // +2 for \n\n
        continue;
      }

      // If paragraph is too large, split it further
      if (paragraph.length > this.maxChunkSize) {
        const subChunks = this.splitLargeParagraph(paragraph, currentPosition);
        chunks.push(...subChunks);
        currentPosition += paragraph.length + 2;
      } else {
        chunks.push({
          content: paragraph.trim(),
          startPosition: currentPosition,
          endPosition: currentPosition + paragraph.length,
          sectionType: this.detectSectionType(paragraph),
          metadata: this.extractMetadata(paragraph)
        });
        currentPosition += paragraph.length + 2;
      }
    }

    return chunks;
  }

  /**
   * Split large paragraphs into smaller chunks
   */
  private splitLargeParagraph(
    paragraph: string,
    startPosition: number
  ): Array<{
    content: string;
    startPosition: number;
    endPosition: number;
    sectionType?: string;
    metadata?: Record<string, any>;
  }> {
    const chunks: Array<{
      content: string;
      startPosition: number;
      endPosition: number;
      sectionType?: string;
      metadata?: Record<string, any>;
    }> = [];

    // Split by sentences first
    const sentences = paragraph.match(/[^.!?]+[.!?]+/g) || [paragraph];
    let currentChunk = '';
    let chunkStartPosition = startPosition;

    for (const sentence of sentences) {
      if ((currentChunk + sentence).length > this.maxChunkSize && currentChunk.length > 0) {
        // Store current chunk and start new one
        chunks.push({
          content: currentChunk.trim(),
          startPosition: chunkStartPosition,
          endPosition: chunkStartPosition + currentChunk.length,
          sectionType: this.detectSectionType(currentChunk),
          metadata: this.extractMetadata(currentChunk)
        });
        currentChunk = sentence;
        chunkStartPosition = chunkStartPosition + currentChunk.length;
      } else {
        currentChunk += sentence;
      }
    }

    // Add the last chunk
    if (currentChunk.trim().length > 0) {
      chunks.push({
        content: currentChunk.trim(),
        startPosition: chunkStartPosition,
        endPosition: chunkStartPosition + currentChunk.length,
        sectionType: this.detectSectionType(currentChunk),
        metadata: this.extractMetadata(currentChunk)
      });
    }

    return chunks;
  }

  /**
   * Detect section type based on content
   */
  private detectSectionType(content: string): string {
    const lowerContent = content.toLowerCase();
    
    if (lowerContent.includes('financial') || lowerContent.includes('revenue') || lowerContent.includes('ebitda')) {
      return 'financial';
    } else if (lowerContent.includes('market') || lowerContent.includes('industry') || lowerContent.includes('competition')) {
      return 'market';
    } else if (lowerContent.includes('technology') || lowerContent.includes('software') || lowerContent.includes('platform')) {
      return 'technology';
    } else if (lowerContent.includes('management') || lowerContent.includes('team') || lowerContent.includes('leadership')) {
      return 'management';
    } else if (lowerContent.includes('risk') || lowerContent.includes('challenge') || lowerContent.includes('opportunity')) {
      return 'risk_opportunity';
    }
    
    return 'general';
  }

  /**
   * Extract metadata from content
   */
  private extractMetadata(content: string): Record<string, any> {
    const metadata: Record<string, any> = {};
    
    // Extract key metrics
    const revenueMatch = content.match(/\$[\d,]+(?:\.\d+)?\s*(?:million|billion|M|B)/gi);
    if (revenueMatch) {
      metadata['revenueMentions'] = revenueMatch.length;
    }

    // Extract company names
    const companyMatch = content.match(/\b[A-Z][a-z]+(?:\s+[A-Z][a-z]+)*\s+(?:Inc|Corp|LLC|Ltd|Company|Group)\b/g);
    if (companyMatch) {
      metadata['companies'] = companyMatch;
    }

    // Extract financial terms
    const financialTerms = ['revenue', 'ebitda', 'profit', 'margin', 'growth', 'valuation'];
    metadata['financialTerms'] = financialTerms.filter(term => 
      content.toLowerCase().includes(term)
    );

    return metadata;
  }

  /**
   * Process chunks in batches to manage memory and API limits
   */
  private async processChunksInBatches(
    chunks: ProcessingChunk[],
    documentId: string,
    options: {
      enableMetadataEnrichment?: boolean;
      similarityThreshold?: number;
    }
  ): Promise<ProcessingChunk[]> {
    const processedChunks: ProcessingChunk[] = [];
    
    // Process chunks in batches
    for (let i = 0; i < chunks.length; i += this.batchSize) {
      const batch = chunks.slice(i, i + this.batchSize);
      
      logger.info(`Processing batch ${Math.floor(i / this.batchSize) + 1}/${Math.ceil(chunks.length / this.batchSize)} for document: ${documentId}`);
      
      // Process batch with concurrency control
      const batchPromises = batch.map(async (chunk, batchIndex) => {
        try {
          // Add delay to respect API rate limits
          if (batchIndex > 0) {
            await new Promise(resolve => setTimeout(resolve, 100));
          }

          // Enrich metadata if enabled
          if (options.enableMetadataEnrichment) {
            chunk.metadata = {
              ...chunk.metadata,
              ...this.enrichChunkMetadata(chunk)
            };
          }

          return chunk;
        } catch (error) {
          logger.error(`Failed to process chunk ${chunk.chunkIndex}`, error);
          return null;
        }
      });

      const batchResults = await Promise.all(batchPromises);
      processedChunks.push(...batchResults.filter(chunk => chunk !== null) as ProcessingChunk[]);

      // Force garbage collection between batches
      if (global.gc) {
        global.gc();
      }

      // Log memory usage
      const memoryUsage = process.memoryUsage();
      logger.info(`Batch completed. Memory usage: ${Math.round(memoryUsage.heapUsed / 1024 / 1024)}MB`);
    }

    return processedChunks;
  }

  /**
   * Enrich chunk metadata with additional analysis
   */
  private enrichChunkMetadata(chunk: ProcessingChunk): Record<string, any> {
    const metadata: Record<string, any> = {
      chunkSize: chunk.content.length,
      wordCount: chunk.content.split(/\s+/).length,
      sentenceCount: (chunk.content.match(/[.!?]+/g) || []).length,
      hasNumbers: /\d/.test(chunk.content),
      hasFinancialData: /revenue|ebitda|profit|margin|growth|valuation/i.test(chunk.content),
      hasTechnicalData: /technology|software|platform|api|database/i.test(chunk.content),
      processingTimestamp: new Date().toISOString()
    };

    return metadata;
  }

  /**
   * Store chunks with optimized batching
   */
  private async storeChunksOptimized(
    chunks: ProcessingChunk[],
    documentId: string
  ): Promise<void> {
    try {
      // Generate embeddings in parallel with rate limiting
      const chunksWithEmbeddings = await this.generateEmbeddingsWithRateLimit(chunks);

      // Store in batches
      const storeBatchSize = 20;
      for (let i = 0; i < chunksWithEmbeddings.length; i += storeBatchSize) {
        const batch = chunksWithEmbeddings.slice(i, i + storeBatchSize);
        
        await VectorDatabaseModel.storeDocumentChunks(
          batch.map(chunk => ({
            documentId: chunk.documentId,
            content: chunk.content,
            metadata: chunk.metadata || {},
            embedding: chunk.embedding,
            chunkIndex: chunk.chunkIndex,
            section: chunk.sectionType || 'general',
            pageNumber: chunk.metadata?.['pageNumber']
          }))
        );

        logger.info(`Stored batch ${Math.floor(i / storeBatchSize) + 1}/${Math.ceil(chunksWithEmbeddings.length / storeBatchSize)} for document: ${documentId}`);
      }

      logger.info(`Successfully stored ${chunksWithEmbeddings.length} chunks for document: ${documentId}`);
    } catch (error) {
      logger.error(`Failed to store chunks for document: ${documentId}`, error);
      throw error;
    }
  }

  /**
   * Generate embeddings with rate limiting and error handling
   */
  private async generateEmbeddingsWithRateLimit(
    chunks: ProcessingChunk[]
  ): Promise<Array<ProcessingChunk & { embedding: number[]; documentId: string }>> {
    const chunksWithEmbeddings: Array<ProcessingChunk & { embedding: number[]; documentId: string }> = [];
    
    // Process with concurrency control
    for (let i = 0; i < chunks.length; i += this.maxConcurrentEmbeddings) {
      const batch = chunks.slice(i, i + this.maxConcurrentEmbeddings);
      
      const batchPromises = batch.map(async (chunk, batchIndex) => {
        try {
          // Add delay between API calls
          if (batchIndex > 0) {
            await new Promise(resolve => setTimeout(resolve, 200));
          }

          const embedding = await vectorDatabaseService.generateEmbeddings(chunk.content);
          
          return {
            ...chunk,
            embedding,
            documentId: chunk.id.split('-chunk-')[0] // Extract document ID from chunk ID
          };
        } catch (error) {
          logger.error(`Failed to generate embedding for chunk ${chunk.chunkIndex}`, error);
          // Return null for failed chunks
          return null;
        }
      });

      const batchResults = await Promise.all(batchPromises);
      chunksWithEmbeddings.push(...batchResults.filter(chunk => chunk !== null) as Array<ProcessingChunk & { embedding: number[]; documentId: string }>);

      // Log progress
      logger.info(`Generated embeddings for ${chunksWithEmbeddings.length}/${chunks.length} chunks`);
    }

    return chunksWithEmbeddings;
  }

  /**
   * Generate LLM analysis using the vectorized chunks
   */
  private async generateLLMAnalysis(
    documentId: string,
    text: string,
    chunks: ProcessingChunk[]
  ): Promise<{ summary: string; analysisData: CIMReview }> {
    try {
      logger.info(`Generating LLM analysis for document: ${documentId} with ${chunks.length} chunks`);
      
      // Use the existing LLM service to generate CIM review
      const result = await llmService.processCIMDocument(text, 'BPCP CIM Review Template');
      
      // Generate a comprehensive summary from the analysis data
      const analysisData = result.jsonOutput || {} as CIMReview;
      const summary = this.generateSummaryFromAnalysis(analysisData);
      
      return {
        summary,
        analysisData
      };
    } catch (error) {
      logger.error(`Failed to generate LLM analysis for document: ${documentId}`, error);
      // Return default values if LLM analysis fails
      return {
        summary: 'Document processed with optimized agentic RAG (LLM analysis failed)',
        analysisData: {} as CIMReview
      };
    }
  }

  /**
   * Generate a comprehensive summary from analysis data
   */
  private generateSummaryFromAnalysis(analysisData: CIMReview): string {
    let summary = '# CIM Review Summary\n\n';
    
    // Add deal overview
    if (analysisData.dealOverview?.targetCompanyName) {
      summary += `## Deal Overview\n\n`;
      summary += `**Target Company:** ${analysisData.dealOverview.targetCompanyName}\n\n`;
      
      if (analysisData.dealOverview.industrySector) {
        summary += `**Industry:** ${analysisData.dealOverview.industrySector}\n\n`;
      }
      if (analysisData.dealOverview.transactionType) {
        summary += `**Transaction Type:** ${analysisData.dealOverview.transactionType}\n\n`;
      }
      if (analysisData.dealOverview.geography) {
        summary += `**Geography:** ${analysisData.dealOverview.geography}\n\n`;
      }
      if (analysisData.dealOverview.employeeCount) {
        summary += `**Employee Count:** ${analysisData.dealOverview.employeeCount}\n\n`;
      }
      if (analysisData.dealOverview.dealSource) {
        summary += `**Deal Source:** ${analysisData.dealOverview.dealSource}\n\n`;
      }
      if (analysisData.dealOverview.statedReasonForSale) {
        summary += `**Reason for Sale:** ${analysisData.dealOverview.statedReasonForSale}\n\n`;
      }
    }
    
    // Add business description
    if (analysisData.businessDescription?.coreOperationsSummary) {
      summary += `## Business Description\n\n`;
      summary += `**Core Operations:** ${analysisData.businessDescription.coreOperationsSummary}\n\n`;
      
      if (analysisData.businessDescription.keyProductsServices) {
        summary += `**Key Products/Services:** ${analysisData.businessDescription.keyProductsServices}\n\n`;
      }
      if (analysisData.businessDescription.uniqueValueProposition) {
        summary += `**Unique Value Proposition:** ${analysisData.businessDescription.uniqueValueProposition}\n\n`;
      }
      
      // Add customer base overview
      if (analysisData.businessDescription.customerBaseOverview) {
        summary += `### Customer Base Overview\n\n`;
        if (analysisData.businessDescription.customerBaseOverview.keyCustomerSegments) {
          summary += `**Key Customer Segments:** ${analysisData.businessDescription.customerBaseOverview.keyCustomerSegments}\n\n`;
        }
        if (analysisData.businessDescription.customerBaseOverview.customerConcentrationRisk) {
          summary += `**Customer Concentration Risk:** ${analysisData.businessDescription.customerBaseOverview.customerConcentrationRisk}\n\n`;
        }
        if (analysisData.businessDescription.customerBaseOverview.typicalContractLength) {
          summary += `**Typical Contract Length:** ${analysisData.businessDescription.customerBaseOverview.typicalContractLength}\n\n`;
        }
      }
      
      // Add supplier overview
      if (analysisData.businessDescription.keySupplierOverview?.dependenceConcentrationRisk) {
        summary += `**Supplier Dependence Risk:** ${analysisData.businessDescription.keySupplierOverview.dependenceConcentrationRisk}\n\n`;
      }
    }
    
    // Add market analysis
    if (analysisData.marketIndustryAnalysis?.estimatedMarketSize) {
      summary += `## Market & Industry Analysis\n\n`;
      summary += `**Market Size:** ${analysisData.marketIndustryAnalysis.estimatedMarketSize}\n\n`;
      
      if (analysisData.marketIndustryAnalysis.estimatedMarketGrowthRate) {
        summary += `**Market Growth Rate:** ${analysisData.marketIndustryAnalysis.estimatedMarketGrowthRate}\n\n`;
      }
      if (analysisData.marketIndustryAnalysis.keyIndustryTrends) {
        summary += `**Industry Trends:** ${analysisData.marketIndustryAnalysis.keyIndustryTrends}\n\n`;
      }
      if (analysisData.marketIndustryAnalysis.barriersToEntry) {
        summary += `**Barriers to Entry:** ${analysisData.marketIndustryAnalysis.barriersToEntry}\n\n`;
      }
      
      // Add competitive landscape
      if (analysisData.marketIndustryAnalysis.competitiveLandscape) {
        summary += `### Competitive Landscape\n\n`;
        if (analysisData.marketIndustryAnalysis.competitiveLandscape.keyCompetitors) {
          summary += `**Key Competitors:** ${analysisData.marketIndustryAnalysis.competitiveLandscape.keyCompetitors}\n\n`;
        }
        if (analysisData.marketIndustryAnalysis.competitiveLandscape.targetMarketPosition) {
          summary += `**Market Position:** ${analysisData.marketIndustryAnalysis.competitiveLandscape.targetMarketPosition}\n\n`;
        }
        if (analysisData.marketIndustryAnalysis.competitiveLandscape.basisOfCompetition) {
          summary += `**Basis of Competition:** ${analysisData.marketIndustryAnalysis.competitiveLandscape.basisOfCompetition}\n\n`;
        }
      }
    }
    
    // Add financial summary
    if (analysisData.financialSummary?.financials) {
      summary += `## Financial Summary\n\n`;
      const financials = analysisData.financialSummary.financials;
      
      // Create financial table
      summary += `<table class="financial-table">\n`;
      summary += `<thead>\n<tr>\n<th>Metric</th>\n`;
      
      const periods: string[] = [];
      if (financials.fy1) periods.push('FY1');
      if (financials.fy2) periods.push('FY2');
      if (financials.fy3) periods.push('FY3');
      if (financials.ltm) periods.push('LTM');
      
      periods.forEach(period => {
        summary += `<th>${period}</th>\n`;
      });
      summary += `</tr>\n</thead>\n<tbody>\n`;
      
      // Revenue row
      if (financials.fy1?.revenue || financials.fy2?.revenue || financials.fy3?.revenue || financials.ltm?.revenue) {
        summary += `<tr>\n<td><strong>Revenue</strong></td>\n`;
        periods.forEach(period => {
          let value = '-';
          if (period === 'FY1' && financials.fy1?.revenue) value = financials.fy1.revenue;
          else if (period === 'FY2' && financials.fy2?.revenue) value = financials.fy2.revenue;
          else if (period === 'FY3' && financials.fy3?.revenue) value = financials.fy3.revenue;
          else if (period === 'LTM' && financials.ltm?.revenue) value = financials.ltm.revenue;
          summary += `<td>${value}</td>\n`;
        });
        summary += `</tr>\n`;
      }
      
      // EBITDA row
      if (financials.fy1?.ebitda || financials.fy2?.ebitda || financials.fy3?.ebitda || financials.ltm?.ebitda) {
        summary += `<tr>\n<td><strong>EBITDA</strong></td>\n`;
        periods.forEach(period => {
          let value = '-';
          if (period === 'FY1' && financials.fy1?.ebitda) value = financials.fy1.ebitda;
          else if (period === 'FY2' && financials.fy2?.ebitda) value = financials.fy2.ebitda;
          else if (period === 'FY3' && financials.fy3?.ebitda) value = financials.fy3.ebitda;
          else if (period === 'LTM' && financials.ltm?.ebitda) value = financials.ltm.ebitda;
          summary += `<td>${value}</td>\n`;
        });
        summary += `</tr>\n`;
      }
      
      // EBITDA Margin row
      if (financials.fy1?.ebitdaMargin || financials.fy2?.ebitdaMargin || financials.fy3?.ebitdaMargin || financials.ltm?.ebitdaMargin) {
        summary += `<tr>\n<td><strong>EBITDA Margin</strong></td>\n`;
        periods.forEach(period => {
          let value = '-';
          if (period === 'FY1' && financials.fy1?.ebitdaMargin) value = financials.fy1.ebitdaMargin;
          else if (period === 'FY2' && financials.fy2?.ebitdaMargin) value = financials.fy2.ebitdaMargin;
          else if (period === 'FY3' && financials.fy3?.ebitdaMargin) value = financials.fy3.ebitdaMargin;
          else if (period === 'LTM' && financials.ltm?.ebitdaMargin) value = financials.ltm.ebitdaMargin;
          summary += `<td>${value}</td>\n`;
        });
        summary += `</tr>\n`;
      }
      
      // Revenue Growth row
      if (financials.fy1?.revenueGrowth || financials.fy2?.revenueGrowth || financials.fy3?.revenueGrowth || financials.ltm?.revenueGrowth) {
        summary += `<tr>\n<td><strong>Revenue Growth</strong></td>\n`;
        periods.forEach(period => {
          let value = '-';
          if (period === 'FY1' && financials.fy1?.revenueGrowth) value = financials.fy1.revenueGrowth;
          else if (period === 'FY2' && financials.fy2?.revenueGrowth) value = financials.fy2.revenueGrowth;
          else if (period === 'FY3' && financials.fy3?.revenueGrowth) value = financials.fy3.revenueGrowth;
          else if (period === 'LTM' && financials.ltm?.revenueGrowth) value = financials.ltm.revenueGrowth;
          summary += `<td>${value}</td>\n`;
        });
        summary += `</tr>\n`;
      }
      
      summary += `</tbody>\n</table>\n\n`;
      
      // Add financial notes
      if (analysisData.financialSummary.qualityOfEarnings) {
        summary += `**Quality of Earnings:** ${analysisData.financialSummary.qualityOfEarnings}\n\n`;
      }
      if (analysisData.financialSummary.revenueGrowthDrivers) {
        summary += `**Revenue Growth Drivers:** ${analysisData.financialSummary.revenueGrowthDrivers}\n\n`;
      }
      if (analysisData.financialSummary.marginStabilityAnalysis) {
        summary += `**Margin Stability:** ${analysisData.financialSummary.marginStabilityAnalysis}\n\n`;
      }
      if (analysisData.financialSummary.capitalExpenditures) {
        summary += `**Capital Expenditures:** ${analysisData.financialSummary.capitalExpenditures}\n\n`;
      }
      if (analysisData.financialSummary.workingCapitalIntensity) {
        summary += `**Working Capital Intensity:** ${analysisData.financialSummary.workingCapitalIntensity}\n\n`;
      }
      if (analysisData.financialSummary.freeCashFlowQuality) {
        summary += `**Free Cash Flow Quality:** ${analysisData.financialSummary.freeCashFlowQuality}\n\n`;
      }
    }
    
    // Add management team
    if (analysisData.managementTeamOverview?.keyLeaders) {
      summary += `## Management Team\n\n`;
      summary += `**Key Leaders:** ${analysisData.managementTeamOverview.keyLeaders}\n\n`;
      
      if (analysisData.managementTeamOverview.managementQualityAssessment) {
        summary += `**Quality Assessment:** ${analysisData.managementTeamOverview.managementQualityAssessment}\n\n`;
      }
      if (analysisData.managementTeamOverview.postTransactionIntentions) {
        summary += `**Post-Transaction Intentions:** ${analysisData.managementTeamOverview.postTransactionIntentions}\n\n`;
      }
      if (analysisData.managementTeamOverview.organizationalStructure) {
        summary += `**Organizational Structure:** ${analysisData.managementTeamOverview.organizationalStructure}\n\n`;
      }
    }
    
    // Add investment thesis
    if (analysisData.preliminaryInvestmentThesis?.keyAttractions) {
      summary += `## Investment Thesis\n\n`;
      summary += `**Key Attractions:** ${analysisData.preliminaryInvestmentThesis.keyAttractions}\n\n`;
      
      if (analysisData.preliminaryInvestmentThesis.potentialRisks) {
        summary += `**Potential Risks:** ${analysisData.preliminaryInvestmentThesis.potentialRisks}\n\n`;
      }
      if (analysisData.preliminaryInvestmentThesis.valueCreationLevers) {
        summary += `**Value Creation Levers:** ${analysisData.preliminaryInvestmentThesis.valueCreationLevers}\n\n`;
      }
      if (analysisData.preliminaryInvestmentThesis.alignmentWithFundStrategy) {
        summary += `**Alignment with Fund Strategy:** ${analysisData.preliminaryInvestmentThesis.alignmentWithFundStrategy}\n\n`;
      }
    }
    
    // Add key questions and next steps
    if (analysisData.keyQuestionsNextSteps?.criticalQuestions) {
      summary += `## Key Questions & Next Steps\n\n`;
      summary += `**Critical Questions:** ${analysisData.keyQuestionsNextSteps.criticalQuestions}\n\n`;
      
      if (analysisData.keyQuestionsNextSteps.missingInformation) {
        summary += `**Missing Information:** ${analysisData.keyQuestionsNextSteps.missingInformation}\n\n`;
      }
      if (analysisData.keyQuestionsNextSteps.preliminaryRecommendation) {
        summary += `**Preliminary Recommendation:** ${analysisData.keyQuestionsNextSteps.preliminaryRecommendation}\n\n`;
      }
      if (analysisData.keyQuestionsNextSteps.rationaleForRecommendation) {
        summary += `**Rationale for Recommendation:** ${analysisData.keyQuestionsNextSteps.rationaleForRecommendation}\n\n`;
      }
      if (analysisData.keyQuestionsNextSteps.proposedNextSteps) {
        summary += `**Proposed Next Steps:** ${analysisData.keyQuestionsNextSteps.proposedNextSteps}\n\n`;
      }
    }
    
    return summary;
  }
}

export const optimizedAgenticRAGProcessor = new OptimizedAgenticRAGProcessor(); 