import { spawn } from 'child_process';
import { join } from 'path';
import { writeFileSync, unlinkSync, existsSync } from 'fs';
import { beforeEach, afterEach, describe, it, expect } from 'vitest';
import { vi } from 'vitest';

const CLI_PATH = join(__dirname, '../../bin/oneshotcat.ts');
const TEST_PROMPT = 'test-prompt.meld.md';
const TEST_OUTPUT = 'test-output.md';
const TEST_EXPANDED = 'test-expanded.md';
const TEST_SYSTEM = 'test-system.md';
const TEST_VARIATIONS_JSON = 'test-variations.json';
const TEST_VARIATIONS_YAML = 'test-variations.yaml';

// Mock environment variables
process.env.ANTHROPIC_API_KEY = 'test-anthropic-key';
process.env.OPENAI_API_KEY = 'test-openai-key';

describe('oneshotcat CLI', () => {
  beforeEach(() => {
    // Create test files
    writeFileSync(TEST_PROMPT, `# Test Prompt

Here's what's in my directory:

@cmd[ls -la]

And here's my Node.js version:

@cmd[node --version]`);
    writeFileSync(TEST_SYSTEM, 'You are a helpful assistant.');
    writeFileSync(TEST_VARIATIONS_JSON, JSON.stringify(['Perspective 1', 'Perspective 2']));
    writeFileSync(TEST_VARIATIONS_YAML, 'architect: "Review as architect"\ndeveloper: "Review as developer"');
  });

  afterEach(() => {
    // Cleanup test files
    [
      TEST_PROMPT,
      TEST_OUTPUT,
      TEST_EXPANDED,
      TEST_SYSTEM,
      TEST_VARIATIONS_JSON,
      TEST_VARIATIONS_YAML
    ].forEach(file => {
      if (existsSync(file)) unlinkSync(file);
    });
  });

  it('should process a prompt script and send to Claude', (done) => {
    const oneshotcat = spawn('ts-node', [CLI_PATH, 'claude-3', TEST_PROMPT]);
    
    let output = '';
    oneshotcat.stdout.on('data', (data) => {
      output += data.toString();
    });

    oneshotcat.stderr.on('data', (data) => {
      console.error(`stderr: ${data}`);
    });

    oneshotcat.on('close', (code) => {
      expect(code).toBe(0);
      expect(output).toContain('🔄 Processing prompt script');
      expect(output).toContain('🤖 Sending prompt to claude-3');
      done();
    });
  });

  it('should support saving expanded prompt', (done) => {
    const oneshotcat = spawn('ts-node', [
      CLI_PATH,
      'claude-3',
      TEST_PROMPT,
      '--meld-outfile',
      TEST_EXPANDED
    ]);
    
    let output = '';
    oneshotcat.stdout.on('data', (data) => {
      output += data.toString();
    });

    oneshotcat.on('close', (code) => {
      expect(code).toBe(0);
      expect(existsSync(TEST_EXPANDED)).toBe(true);
      expect(output).toContain('📝 Expanded prompt written to');
      done();
    });
  });

  it('should support saving final response', (done) => {
    const oneshotcat = spawn('ts-node', [
      CLI_PATH,
      'claude-3',
      TEST_PROMPT,
      '-o',
      TEST_OUTPUT
    ]);
    
    let output = '';
    oneshotcat.stdout.on('data', (data) => {
      output += data.toString();
    });

    oneshotcat.on('close', (code) => {
      expect(code).toBe(0);
      expect(existsSync(TEST_OUTPUT)).toBe(true);
      expect(output).toContain('📝 Response written to');
      done();
    });
  });

  it('should support system prompts and variations', (done) => {
    const oneshotcat = spawn('ts-node', [
      CLI_PATH,
      'claude-3',
      TEST_PROMPT,
      '--system-file',
      TEST_SYSTEM,
      '--variations-file',
      TEST_VARIATIONS_YAML
    ]);
    
    let output = '';
    oneshotcat.stdout.on('data', (data) => {
      output += data.toString();
    });

    oneshotcat.on('close', (code) => {
      expect(code).toBe(0);
      expect(output).toContain('🔄 Processing prompt script');
      expect(output).toContain('🤖 Sending prompt to claude-3');
      done();
    });
  });

  it('should handle command execution errors gracefully', (done) => {
    writeFileSync(TEST_PROMPT, `# Test\n\n@cmd[invalid-command]`);
    
    const oneshotcat = spawn('ts-node', [CLI_PATH, 'claude-3', TEST_PROMPT]);
    
    let stderr = '';
    oneshotcat.stderr.on('data', (data) => {
      stderr += data.toString();
    });

    oneshotcat.on('close', (code) => {
      expect(code).toBe(1);
      expect(stderr).toContain('Error');
      done();
    });
  });

  it('should handle missing prompt file error', (done) => {
    const oneshotcat = spawn('ts-node', [CLI_PATH, 'claude-3', 'nonexistent.md']);
    
    let stderr = '';
    oneshotcat.stderr.on('data', (data) => {
      stderr += data.toString();
    });

    oneshotcat.on('close', (code) => {
      expect(code).toBe(1);
      expect(stderr).toContain('ENOENT');
      done();
    });
  });

  it('should handle missing API key error', (done) => {
    // Temporarily unset API key
    const oldKey = process.env.ANTHROPIC_API_KEY;
    delete process.env.ANTHROPIC_API_KEY;

    const oneshotcat = spawn('ts-node', [CLI_PATH, 'claude-3', TEST_PROMPT]);
    
    let stderr = '';
    oneshotcat.stderr.on('data', (data) => {
      stderr += data.toString();
    });

    oneshotcat.on('close', (code) => {
      // Restore API key
      process.env.ANTHROPIC_API_KEY = oldKey;
      
      expect(code).toBe(1);
      expect(stderr).toContain('Anthropic API key is required');
      done();
    });
  });
}); 