import { spawn } from 'child_process';
import { join } from 'path';
import { writeFileSync, unlinkSync, existsSync, readFileSync } from 'fs';
import { beforeEach, afterEach, describe, it, expect } from 'vitest';
import { homedir } from 'os';
import { RC_FILE } from '../../src/config';

const CLI_PATH = join(__dirname, '../../bin/meld-config.ts');
const RC_PATH = join(homedir(), RC_FILE);

describe('meld-config CLI', () => {
  let originalRcContent: string | null = null;

  beforeEach(() => {
    // Backup existing config if it exists
    if (existsSync(RC_PATH)) {
      originalRcContent = readFileSync(RC_PATH, 'utf-8');
    }
  });

  afterEach(() => {
    // Restore original config or remove test config
    if (originalRcContent) {
      writeFileSync(RC_PATH, originalRcContent);
    } else if (existsSync(RC_PATH)) {
      unlinkSync(RC_PATH);
    }
  });

  it('should show help when no options provided', (done) => {
    const config = spawn('ts-node', [CLI_PATH]);
    
    let output = '';
    config.stdout.on('data', (data) => {
      output += data.toString();
    });

    config.on('close', (code) => {
      expect(code).toBe(1);
      expect(output).toContain('No configuration options provided');
      expect(output).toContain('Available options');
      done();
    });
  });

  it('should set Anthropic API key', (done) => {
    const config = spawn('ts-node', [
      CLI_PATH,
      '--anthropic-key',
      'test-key'
    ]);
    
    let output = '';
    config.stdout.on('data', (data) => {
      output += data.toString();
    });

    config.on('close', (code) => {
      expect(code).toBe(0);
      expect(output).toContain('Configuration updated successfully');
      expect(output).toContain('Set Anthropic API key');

      // Verify config file
      const content = JSON.parse(readFileSync(RC_PATH, 'utf-8'));
      expect(content.anthropicApiKey).toBe('test-key');
      done();
    });
  });

  it('should set OpenAI API key', (done) => {
    const config = spawn('ts-node', [
      CLI_PATH,
      '--openai-key',
      'test-key'
    ]);
    
    let output = '';
    config.stdout.on('data', (data) => {
      output += data.toString();
    });

    config.on('close', (code) => {
      expect(code).toBe(0);
      expect(output).toContain('Configuration updated successfully');
      expect(output).toContain('Set OpenAI API key');

      // Verify config file
      const content = JSON.parse(readFileSync(RC_PATH, 'utf-8'));
      expect(content.openaiApiKey).toBe('test-key');
      done();
    });
  });

  it('should set default model', (done) => {
    const config = spawn('ts-node', [
      CLI_PATH,
      '--default-model',
      'claude-3'
    ]);
    
    let output = '';
    config.stdout.on('data', (data) => {
      output += data.toString();
    });

    config.on('close', (code) => {
      expect(code).toBe(0);
      expect(output).toContain('Configuration updated successfully');
      expect(output).toContain('Set default model to: claude-3');

      // Verify config file
      const content = JSON.parse(readFileSync(RC_PATH, 'utf-8'));
      expect(content.defaultModel).toBe('claude-3');
      done();
    });
  });

  it('should show current configuration', (done) => {
    // First set some config
    writeFileSync(RC_PATH, JSON.stringify({
      defaultModel: 'claude-3',
      anthropicApiKey: 'test-key'
    }));

    const config = spawn('ts-node', [CLI_PATH, '--show']);
    
    let output = '';
    config.stdout.on('data', (data) => {
      output += data.toString();
    });

    config.on('close', (code) => {
      expect(code).toBe(0);
      expect(output).toContain('Current Configuration');
      expect(output).toContain('Default Model: claude-3');
      expect(output).toContain('Anthropic API Key: ✓');
      expect(output).toContain('OpenAI API Key: ✗');
      done();
    });
  });

  it('should preserve existing config when updating', (done) => {
    // First set some initial config
    writeFileSync(RC_PATH, JSON.stringify({
      defaultModel: 'claude-3',
      anthropicApiKey: 'existing-key'
    }));

    const config = spawn('ts-node', [
      CLI_PATH,
      '--openai-key',
      'new-key'
    ]);
    
    let output = '';
    config.stdout.on('data', (data) => {
      output += data.toString();
    });

    config.on('close', (code) => {
      expect(code).toBe(0);
      expect(output).toContain('Configuration updated successfully');

      // Verify config file
      const content = JSON.parse(readFileSync(RC_PATH, 'utf-8'));
      expect(content.defaultModel).toBe('claude-3');
      expect(content.anthropicApiKey).toBe('existing-key');
      expect(content.openaiApiKey).toBe('new-key');
      done();
    });
  });
}); 