import { describe, test, expect, vi, beforeEach } from 'vitest';
import { mockFs, mockChildProcess, setupMocks } from './utils';
import { Oneshotcat } from '../src/oneshotcat';

// Setup mocks before imports
setupMocks();

// Mock config module
vi.mock('../src/config', () => ({
  loadConfig: () => ({
    anthropicApiKey: 'mock-anthropic-key',
    openaiApiKey: 'mock-openai-key'
  })
}));

// Mock AI providers
vi.mock('../src/providers/anthropic', () => ({
  AnthropicProvider: class {
    constructor() {}
    async sendPrompt() {
      return 'mock response';
    }
  }
}));

describe('Oneshotcat', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    mockFs.existsSync.mockReturnValue(true);
    mockFs.readFileSync.mockReturnValue('');
    mockFs.writeFileSync.mockImplementation(() => {});
    mockFs.unlinkSync.mockImplementation(() => {});
  });

  test('processes prompt script and sends to AI', async () => {
    const content = '# Test\n@cmd[echo "test output"]';
    mockFs.readFileSync.mockReturnValue(content);
    mockChildProcess.execSync.mockReturnValue('test output\n');

    const cat = new Oneshotcat({
      inputFile: 'test.md',
      model: 'claude-3'
    });

    const result = await cat.process();
    expect(result).toEqual([{
      variation: undefined,
      systemPrompt: '',
      response: 'mock response'
    }]);

    // Verify command was executed with correct options
    expect(mockChildProcess.execSync).toHaveBeenCalledWith(
      'echo "test output"',
      expect.objectContaining({
        encoding: 'utf-8',
        stdio: ['pipe', 'pipe', 'pipe']
      })
    );
  });

  test('handles command execution errors gracefully', async () => {
    const content = '# Test\n@cmd[invalid-command]';
    mockFs.readFileSync.mockReturnValue(content);
    
    const mockError = new Error('command not found');
    mockError.stderr = 'command not found error';
    mockError.stdout = '';
    mockError.code = 1;
    mockChildProcess.execSync.mockImplementation(() => {
      throw mockError;
    });

    const cat = new Oneshotcat({
      inputFile: 'test.md',
      model: 'claude-3'
    });

    const result = await cat.process();
    expect(result).toEqual([{
      variation: undefined,
      systemPrompt: '',
      response: 'mock response'
    }]);

    // Verify error was handled and included in output
    expect(mockFs.writeFileSync).toHaveBeenCalled();
    const calls = mockFs.writeFileSync.mock.calls;
    const writtenContent = calls[0][1];  // First call's second argument is the content
    expect(writtenContent).toContain('Error: Error processing cmd directive');
  });

  test('throws error if input file does not exist', async () => {
    mockFs.existsSync.mockReturnValue(false);

    const cat = new Oneshotcat({
      inputFile: 'nonexistent.md',
      model: 'claude-3'
    });

    await expect(cat.process()).rejects.toThrow();
  });
}); 