import { llmService } from '../llmService';
import { config } from '../../config/env';

// Mock dependencies
jest.mock('../../config/env');
jest.mock('openai');
jest.mock('@anthropic-ai/sdk');

const mockConfig = config as jest.Mocked<typeof config>;

describe('LLMService', () => {
  const mockExtractedText = `This is a test CIM document for ABC Company.
  
  The company operates in the technology sector and has shown strong growth.
  Revenue has increased by 25% year over year to $50 million.
  The market size is estimated at $10 billion with 15% annual growth.
  
  Key financial metrics:
  - Revenue: $50M
  - EBITDA: $15M
  - Growth Rate: 25%
  - Market Share: 5%
  
  The competitive landscape includes Microsoft, Google, and Amazon.
  The company has a strong market position with unique AI technology.
  
  Management team consists of experienced executives from major tech companies.
  The company is headquartered in San Francisco, CA.`;

  const mockTemplate = `# BPCP CIM Review Template

## (A) Deal Overview
- Target Company Name:
- Industry/Sector:
- Geography (HQ & Key Operations):
- Deal Source:
- Transaction Type:
- Date CIM Received:
- Date Reviewed:
- Reviewer(s):
- CIM Page Count:
- Stated Reason for Sale:

## (B) Business Description
- Core Operations Summary:
- Key Products/Services & Revenue Mix:
- Unique Value Proposition:
- Customer Base Overview:
- Key Supplier Overview:

## (C) Market & Industry Analysis
- Market Size:
- Growth Rate:
- Key Drivers:
- Competitive Landscape:
- Regulatory Environment:

## (D) Financial Overview
- Revenue:
- EBITDA:
- Margins:
- Growth Trends:
- Key Metrics:

## (E) Competitive Landscape
- Competitors:
- Competitive Advantages:
- Market Position:
- Threats:

## (F) Investment Thesis
- Key Attractions:
- Potential Risks:
- Value Creation Levers:
- Alignment with Fund Strategy:

## (G) Key Questions & Next Steps
- Critical Questions:
- Missing Information:
- Preliminary Recommendation:
- Rationale:
- Next Steps:`;

  beforeEach(() => {
    jest.clearAllMocks();
    
    // Mock config
    mockConfig.llm = {
      provider: 'openai',
      openaiApiKey: 'test-key',
      anthropicApiKey: 'test-key',
      model: 'test-model',
      fastModel: 'test-fast-model',
      fallbackModel: 'test-fallback-model',
      maxTokens: 8000,
      maxInputTokens: 6000,
      chunkSize: 2000,
      promptBuffer: 200,
      temperature: 0.5,
      timeoutMs: 10000,
      enableCostOptimization: true,
      maxCostPerDocument: 0.05,
      useFastModelForSimpleTasks: true,
    };
  });

  describe('processCIMDocument', () => {
    it('should process CIM document successfully', async () => {
      // Mock OpenAI response
      const mockOpenAI = require('openai');
      const mockCompletion = {
        choices: [{ message: { content: JSON.stringify({
          dealOverview: {
            targetCompanyName: 'ABC Company',
            industrySector: 'Technology',
            geography: 'San Francisco, CA',
          },
          businessDescription: {
            coreOperationsSummary: 'Technology company with AI focus',
          },
        }) } }],
        usage: {
          prompt_tokens: 1000,
          completion_tokens: 500,
          total_tokens: 1500,
        },
      };
      
      mockOpenAI.default = jest.fn().mockImplementation(() => ({
        chat: {
          completions: {
            create: jest.fn().mockResolvedValue(mockCompletion),
          },
        },
      }));

      const result = await llmService.processCIMDocument(mockExtractedText, mockTemplate);

      expect(result).toBeDefined();
      expect(result.success).toBe(true);
      expect(result.jsonOutput).toBeDefined();
    });

    it('should handle OpenAI API errors', async () => {
      const mockOpenAI = require('openai');
      mockOpenAI.default = jest.fn().mockImplementation(() => ({
        chat: {
          completions: {
            create: jest.fn().mockRejectedValue(new Error('OpenAI API error')),
          },
        },
      }));

      await expect(llmService.processCIMDocument(mockExtractedText, mockTemplate))
        .rejects.toThrow('LLM processing failed');
    });

    it('should use Anthropic when configured', async () => {
      mockConfig.llm.provider = 'anthropic';
      
      const mockAnthropic = require('@anthropic-ai/sdk');
      const mockMessage = {
        content: [{ type: 'text', text: JSON.stringify({
          dealOverview: { targetCompanyName: 'ABC Company' },
          businessDescription: { coreOperationsSummary: 'Test summary' },
        }) }],
        usage: {
          input_tokens: 1000,
          output_tokens: 500,
        },
      };
      
      mockAnthropic.default = jest.fn().mockImplementation(() => ({
        messages: {
          create: jest.fn().mockResolvedValue(mockMessage),
        },
      }));

      const result = await llmService.processCIMDocument(mockExtractedText, mockTemplate);

      expect(result).toBeDefined();
      expect(mockAnthropic.default).toHaveBeenCalled();
    });

    it('should handle Anthropic API errors', async () => {
      mockConfig.llm.provider = 'anthropic';
      
      const mockAnthropic = require('@anthropic-ai/sdk');
      mockAnthropic.default = jest.fn().mockImplementation(() => ({
        messages: {
          create: jest.fn().mockRejectedValue(new Error('Anthropic API error')),
        },
      }));

      await expect(llmService.processCIMDocument(mockExtractedText, mockTemplate))
        .rejects.toThrow('LLM processing failed');
    });

    it('should handle unsupported provider', async () => {
      mockConfig.llm.provider = 'unsupported' as any;

      await expect(llmService.processCIMDocument(mockExtractedText, mockTemplate))
        .rejects.toThrow('LLM processing failed');
    });
  });

  

  describe('error handling', () => {
    it('should handle missing API keys', async () => {
      mockConfig.llm.openaiApiKey = undefined;
      mockConfig.llm.anthropicApiKey = undefined;

      await expect(llmService.processCIMDocument(mockExtractedText, mockTemplate))
        .rejects.toThrow('LLM processing failed');
    });

    it('should handle empty extracted text', async () => {
      await expect(llmService.processCIMDocument('', mockTemplate))
        .rejects.toThrow('LLM processing failed');
    });

    it('should handle empty template', async () => {
      await expect(llmService.processCIMDocument(mockExtractedText, ''))
        .rejects.toThrow('LLM processing failed');
    });
  });
}); 