import { describe, it, expect } from 'vitest';
import { getErrorMessage, formatErrorMessage, formatErrorForLogging } from './error-messages';

describe('Error Messages Utility', () => {
  describe('getErrorMessage', () => {
    it('should identify network errors', () => {
      const error = new Error('getaddrinfo ENOTFOUND github.com');
      const result = getErrorMessage(error);

      expect(result.title).toBe('Network Connection Error');
      expect(result.possibleCauses).toContain('No internet connection');
      expect(result.suggestedActions).toContain('Check your internet connection');
    });

    it('should identify permission errors', () => {
      const error = new Error('EACCES: permission denied');
      const result = getErrorMessage(error);

      expect(result.title).toBe('Permission Denied');
      expect(result.possibleCauses).toContain('Insufficient file system permissions');
      expect(result.suggestedActions).toContain('Try running the operation again');
    });

    it('should identify Homebrew command not found errors', () => {
      const error = new Error('brew: command not found');
      const result = getErrorMessage(error, 'homebrew');

      expect(result.title).toBe('Homebrew Not Found');
      expect(result.possibleCauses).toContain('Homebrew is not installed');
      expect(result.suggestedActions?.some(action =>
        action.includes('https://brew.sh')
      )).toBe(true);
    });

    it('should identify Homebrew lock file errors', () => {
      const error = new Error('Waiting for lock on');
      const result = getErrorMessage(error, 'homebrew');

      expect(result.title).toBe('Homebrew Lock File');
      expect(result.possibleCauses).toContain('Another Homebrew process is running');
      expect(result.suggestedActions?.some(action =>
        action.includes('brew cleanup')
      )).toBe(true);
    });

    it('should identify Docker daemon errors', () => {
      const error = new Error('Cannot connect to the Docker daemon');
      const result = getErrorMessage(error, 'docker');

      expect(result.title).toBe('Docker Daemon Not Running');
      expect(result.possibleCauses).toContain('Docker Desktop is not running');
      expect(result.suggestedActions).toContain('Open Docker Desktop application');
    });

    it('should identify SSH authentication errors', () => {
      const error = new Error('Permission denied (publickey)');
      const result = getErrorMessage(error, 'ssh');

      expect(result.title).toBe('SSH Authentication Failed');
      expect(result.possibleCauses).toContain('SSH key not added to your account');
      expect(result.suggestedActions?.some(action =>
        action.includes('ssh -T git@github.com')
      )).toBe(true);
    });

    it('should identify Git repository not found errors', () => {
      const error = new Error('Repository not found');
      const result = getErrorMessage(error, 'git');

      expect(result.title).toBe('Repository Access Error');
      expect(result.possibleCauses).toContain('Repository doesn\'t exist');
      expect(result.suggestedActions).toContain('Verify the repository exists');
    });

    it('should identify file not found errors', () => {
      const error = new Error('ENOENT: no such file or directory');
      const result = getErrorMessage(error);

      expect(result.title).toBe('File or Directory Not Found');
      expect(result.possibleCauses).toContain('File was moved or deleted');
      expect(result.suggestedActions).toContain('Verify the file path is correct');
    });

    it('should identify timeout errors', () => {
      const error = new Error('Operation timeout');
      const result = getErrorMessage(error);

      expect(result.title).toBe('Operation Timed Out');
      expect(result.possibleCauses).toContain('Slow internet connection');
      expect(result.suggestedActions).toContain('Check your internet connection speed');
    });

    it('should handle generic errors', () => {
      const error = new Error('Some random error');
      const result = getErrorMessage(error);

      expect(result.title).toBe('Operation Failed');
      expect(result.possibleCauses).toBeDefined();
      expect(result.suggestedActions).toBeDefined();
      expect(result.technicalDetails).toBe('Some random error');
    });

    it('should handle string errors', () => {
      const result = getErrorMessage('Network error');

      expect(result.title).toBe('Network Connection Error');
      expect(result.technicalDetails).toBe('Network error');
    });

    it('should include context in generic errors', () => {
      const error = new Error('Unknown error');
      const result = getErrorMessage(error, 'install package');

      expect(result.description).toContain('install package');
    });
  });

  describe('formatErrorMessage', () => {
    it('should format a complete error message', () => {
      const errorMsg = {
        title: 'Test Error',
        description: 'This is a test error',
        possibleCauses: ['Cause 1', 'Cause 2'],
        suggestedActions: ['Action 1', 'Action 2'],
        technicalDetails: 'Technical info'
      };

      const formatted = formatErrorMessage(errorMsg);

      expect(formatted).toContain('Test Error');
      expect(formatted).toContain('This is a test error');
      expect(formatted).toContain('Possible causes:');
      expect(formatted).toContain('• Cause 1');
      expect(formatted).toContain('• Cause 2');
      expect(formatted).toContain('Suggested actions:');
      expect(formatted).toContain('1. Action 1');
      expect(formatted).toContain('2. Action 2');
    });

    it('should handle errors without causes', () => {
      const errorMsg = {
        title: 'Test Error',
        description: 'This is a test error',
        suggestedActions: ['Action 1']
      };

      const formatted = formatErrorMessage(errorMsg);

      expect(formatted).toContain('Test Error');
      expect(formatted).not.toContain('Possible causes:');
      expect(formatted).toContain('Suggested actions:');
    });

    it('should handle errors without actions', () => {
      const errorMsg = {
        title: 'Test Error',
        description: 'This is a test error',
        possibleCauses: ['Cause 1']
      };

      const formatted = formatErrorMessage(errorMsg);

      expect(formatted).toContain('Test Error');
      expect(formatted).toContain('Possible causes:');
      expect(formatted).not.toContain('Suggested actions:');
    });
  });

  describe('formatErrorForLogging', () => {
    it('should format error for logging', () => {
      const error = new Error('Test error');
      const formatted = formatErrorForLogging(error, 'test operation');

      expect(formatted).toContain('Operation Failed');
      expect(formatted).toContain('Technical:');
      expect(formatted).toContain('Test error');
    });

    it('should handle timeout errors in logging format', () => {
      const error = new Error('Operation timeout');
      const formatted = formatErrorForLogging(error);

      expect(formatted).toContain('Operation Timed Out');
      expect(formatted).toContain('Operation timeout');
    });
  });
});
