/**
 * Tests for Enhanced Error Handling Generator
 */

import { EnhancedErrorHandlingGenerator } from './enhanced-error-handling-generator';
import { GeneratorContext } from '../types';
import { Workflow } from '../../types/workflow';

describe('EnhancedErrorHandlingGenerator', () => {
  let generator: EnhancedErrorHandlingGenerator;

  beforeEach(() => {
    generator = new EnhancedErrorHandlingGenerator();
  });

  describe('Configuration Generation', () => {
    it('should generate error handling configuration', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          middleware: true,
          logging: {
            provider: 'winston',
            level: 'error',
          },
          tracking: {
            provider: 'sentry',
            frontend: true,
            backend: true,
          },
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      expect(result.files.length).toBeGreaterThan(0);
      const configFile = result.files.find(f => f.path.includes('config/error-handling.ts'));
      expect(configFile).toBeDefined();
      expect(configFile!.content).toContain('winston');
      expect(configFile!.content).toContain('sentry');
    });
  });

  describe('Custom Error Classes', () => {
    it('should generate default error classes', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          middleware: true,
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const errorsFile = result.files.find(f => f.path.includes('errors/custom-errors.ts'));
      expect(errorsFile).toBeDefined();
      expect(errorsFile!.content).toContain('ValidationError');
      expect(errorsFile!.content).toContain('AuthenticationError');
      expect(errorsFile!.content).toContain('NotFoundError');
    });

    it('should generate custom error classes', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          custom_errors: [
            {
              name: 'PaymentError',
              status_code: 402,
              default_message: 'Payment required',
            },
          ],
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const errorsFile = result.files.find(f => f.path.includes('errors/custom-errors.ts'));
      expect(errorsFile).toBeDefined();
      expect(errorsFile!.content).toContain('PaymentError');
      expect(errorsFile!.content).toContain('402');
    });
  });

  describe('Error Middleware', () => {
    it('should generate error middleware when enabled', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          middleware: true,
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const middlewareFile = result.files.find(f => f.path.includes('middleware/error-handler.ts'));
      expect(middlewareFile).toBeDefined();
      expect(middlewareFile!.content).toContain('errorHandler');
      expect(middlewareFile!.content).toContain('asyncHandler');
      expect(middlewareFile!.content).toContain('notFoundHandler');
    });

    it('should not generate middleware when disabled', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          middleware: false,
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const middlewareFile = result.files.find(f => f.path.includes('middleware/error-handler.ts'));
      expect(middlewareFile).toBeUndefined();
    });
  });

  describe('Error Logger', () => {
    it('should generate Winston logger', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          logging: {
            provider: 'winston',
            level: 'error',
          },
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const loggerFile = result.files.find(f => f.path.includes('middleware/error-logger.ts'));
      expect(loggerFile).toBeDefined();
      expect(loggerFile!.content).toContain('winston');
      expect(loggerFile!.content).toContain('errorLogger');
    });

    it('should generate Pino logger', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          logging: {
            provider: 'pino',
            level: 'info',
          },
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const loggerFile = result.files.find(f => f.path.includes('middleware/error-logger.ts'));
      expect(loggerFile).toBeDefined();
      expect(loggerFile!.content).toContain('pino');
    });
  });

  describe('Error Tracking', () => {
    it('should generate Sentry integration', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          tracking: {
            provider: 'sentry',
            backend: true,
          },
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const trackingFile = result.files.find(f => f.path.includes('middleware/error-tracker.ts'));
      expect(trackingFile).toBeDefined();
      expect(trackingFile!.content).toContain('@sentry/node');
      expect(trackingFile!.content).toContain('captureException');
    });
  });

  describe('Frontend Error Boundaries', () => {
    it('should generate error boundary when enabled', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          error_boundaries: {
            enabled: true,
            fallback_ui: 'default',
          },
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const boundaryFile = result.files.find(f => f.path.includes('ErrorBoundary.tsx'));
      expect(boundaryFile).toBeDefined();
      expect(boundaryFile!.content).toContain('ErrorBoundary');
      expect(boundaryFile!.content).toContain('componentDidCatch');

      const fallbackFile = result.files.find(f => f.path.includes('ErrorFallback.tsx'));
      expect(fallbackFile).toBeDefined();
      expect(fallbackFile!.content).toContain('ErrorFallback');
    });

    it('should not generate error boundary when disabled', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          error_boundaries: {
            enabled: false,
          },
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const boundaryFile = result.files.find(f => f.path.includes('ErrorBoundary.tsx'));
      expect(boundaryFile).toBeUndefined();
    });
  });

  describe('Error Formatter', () => {
    it('should generate JSON:API formatter', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          api_formatting: {
            format: 'json_api',
            include_stack: true,
          },
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const formatterFile = result.files.find(f => f.path.includes('error-formatter.ts'));
      expect(formatterFile).toBeDefined();
      expect(formatterFile!.content).toContain('JSON:API format');
      expect(formatterFile!.content).toContain('formatError');
    });

    it('should generate Problem JSON formatter', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          api_formatting: {
            format: 'problem_json',
          },
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const formatterFile = result.files.find(f => f.path.includes('error-formatter.ts'));
      expect(formatterFile).toBeDefined();
      expect(formatterFile!.content).toContain('Problem JSON');
    });
  });

  describe('Error Recovery', () => {
    it('should generate recovery strategies', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
        error_handling: {
          recovery_strategies: [
            {
              error_type: 'NetworkError',
              strategy: 'retry',
              config: { maxAttempts: 3, delay: 1000 },
            },
          ],
        },
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      const recoveryFile = result.files.find(f => f.path.includes('error-recovery.ts'));
      expect(recoveryFile).toBeDefined();
      expect(recoveryFile!.content).toContain('retry');
      expect(recoveryFile!.content).toContain('CircuitBreaker');
      expect(recoveryFile!.content).toContain('withFallback');
    });
  });

  describe('Edge Cases', () => {
    it('should return empty array when error_handling not configured', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0', name: 'Test', description: 'Test workflow' },
        stack: {},
      };

      const context: GeneratorContext = { workflow, outputDirectory: '/tmp/test',
        executionPlan: { workflow, componentPlans: new Map() },
      };

      const result = generator.generate(context);

      expect(result.files).toEqual([]);
    });
  });
});
