/**
 * Tests for EnhancedMonitoringGenerator
 */

import { EnhancedMonitoringGenerator } from './enhanced-monitoring-generator';
import { WorkflowEngine } from '../../engine/workflow-engine';
import { Workflow } from '../../types/workflow';

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

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

  it('should have correct metadata', () => {
    expect(generator.id).toBe('enhanced-monitoring');
    expect(generator.name).toBe('Enhanced Monitoring Generator');
    expect(generator.description).toContain('monitoring and observability');
  });

  it('should return empty result when no monitoring config', () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test',
        name: 'Test',
        version: '1.0.0',
        description: "Test workflow",
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
        },
      },
    };

    const engine = new WorkflowEngine();
    const executionPlan = engine.analyze(workflow);

    const result = generator.generate({
      workflow,
      executionPlan,
      outputDirectory: '/test',
    });

    expect(result.files).toHaveLength(0);
  });

  describe('Logging', () => {
    it('should generate Winston logging configuration', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
        },
        monitoring: {
          logging: {
            provider: 'winston',
            level: 'debug',
            transports: [
              { type: 'console' },
              { type: 'file', config: { filename: 'app.log' } },
            ],
          },
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const loggingConfig = result.files.find(f => f.path.includes('config/logging.ts'));
      expect(loggingConfig).toBeDefined();
      expect(loggingConfig?.content).toContain('winston');
      expect(loggingConfig?.content).toContain("level: 'debug'");
      expect(loggingConfig?.content).toContain('winston.transports.Console');
      expect(loggingConfig?.content).toContain('winston.transports.File');
    });

    it('should generate Pino logging configuration', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
        },
        monitoring: {
          logging: {
            provider: 'pino',
            level: 'info',
          },
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const loggingConfig = result.files.find(f => f.path.includes('config/logging.ts'));
      expect(loggingConfig).toBeDefined();
      expect(loggingConfig?.content).toContain('pino');
      expect(loggingConfig?.content).toContain("level: 'info'");
    });

    it('should generate logger utility file', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
        },
        monitoring: {
          logging: {
            provider: 'winston',
            level: 'info',
          },
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const loggerUtil = result.files.find(f => f.path.includes('utils/logger.ts'));
      expect(loggerUtil).toBeDefined();
      expect(loggerUtil?.content).toContain('logRequest');
      expect(loggerUtil?.content).toContain('logError');
      expect(loggerUtil?.content).toContain('logMetric');
    });
  });

  describe('Error Tracking', () => {
    it('should generate Sentry error tracking for backend', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
        },
        monitoring: {
          error_tracking: {
            provider: 'sentry',
            backend: true,
          },
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const errorTracking = result.files.find(f => f.path.includes('config/error-tracking.ts'));
      expect(errorTracking).toBeDefined();
      expect(errorTracking?.content).toContain('@sentry/node');
      expect(errorTracking?.content).toContain('Sentry.init');
      expect(errorTracking?.content).toContain('captureException');
    });

    it('should generate Bugsnag error tracking', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
        },
        monitoring: {
          error_tracking: {
            provider: 'bugsnag',
            backend: true,
          },
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const errorTracking = result.files.find(f => f.path.includes('config/error-tracking.ts'));
      expect(errorTracking).toBeDefined();
      expect(errorTracking?.content).toContain('@bugsnag/js');
      expect(errorTracking?.content).toContain('Bugsnag.start');
    });

    it('should generate frontend error tracking when enabled', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          web: {
            type: 'frontend',
            technology: 'react',
          },
        },
        monitoring: {
          error_tracking: {
            provider: 'sentry',
            frontend: true,
          },
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const frontendTracking = result.files.find(f => f.path.includes('web/') && f.path.includes('error-tracking.ts'));
      expect(frontendTracking).toBeDefined();
      expect(frontendTracking?.content).toContain('@sentry/react');
      expect(frontendTracking?.content).toContain('BrowserTracing');
    });
  });

  describe('APM', () => {
    it('should generate Datadog APM configuration', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
        },
        monitoring: {
          apm: {
            provider: 'datadog',
          },
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const apmConfig = result.files.find(f => f.path.includes('config/apm.ts'));
      expect(apmConfig).toBeDefined();
      expect(apmConfig?.content).toContain('dd-trace');
      expect(apmConfig?.content).toContain('tracer.init');
    });

    it('should generate New Relic APM configuration', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
        },
        monitoring: {
          apm: {
            provider: 'new_relic',
          },
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const apmConfig = result.files.find(f => f.path.includes('config/apm.ts'));
      expect(apmConfig).toBeDefined();
      expect(apmConfig?.content).toContain('newrelic');
    });

    it('should generate Application Insights APM configuration', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
        },
        monitoring: {
          apm: {
            provider: 'app_insights',
          },
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const apmConfig = result.files.find(f => f.path.includes('config/apm.ts'));
      expect(apmConfig).toBeDefined();
      expect(apmConfig?.content).toContain('applicationinsights');
      expect(apmConfig?.content).toContain('setAutoDependencyCorrelation');
    });
  });

  describe('Distributed Tracing', () => {
    it('should generate tracing configuration', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
        },
        monitoring: {
          tracing: {
            provider: 'jaeger',
            sampling_rate: 0.5,
          },
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const tracingConfig = result.files.find(f => f.path.includes('config/tracing.ts'));
      expect(tracingConfig).toBeDefined();
      expect(tracingConfig?.content).toContain('jaeger');
      expect(tracingConfig?.content).toContain('0.5');
    });
  });

  describe('Metrics', () => {
    it('should generate metrics configuration with custom metrics', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
        },
        monitoring: {
          metrics: {
            tracked: ['requests', 'errors', 'latency'],
            custom_metrics: [
              {
                name: 'user_signups',
                type: 'counter',
                description: 'Number of user signups',
              },
              {
                name: 'active_connections',
                type: 'gauge',
                description: 'Current active connections',
              },
            ],
          },
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const metricsConfig = result.files.find(f => f.path.includes('config/metrics.ts'));
      expect(metricsConfig).toBeDefined();
      expect(metricsConfig?.content).toContain('requests, errors, latency');
      expect(metricsConfig?.content).toContain('user_signups');
      expect(metricsConfig?.content).toContain('active_connections');
    });
  });

  describe('Alerts', () => {
    it('should generate alert configuration file', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
        },
        monitoring: {
          alerts: [
            {
              name: 'high-error-rate',
              condition: 'error_rate > 0.05',
              channels: ['slack', 'email'],
              severity: 'critical',
            },
            {
              name: 'slow-response',
              condition: 'avg_response_time > 1000',
              channels: ['slack'],
              severity: 'warning',
            },
          ],
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      const alertsConfig = result.files.find(f => f.path.includes('alerts.config.ts'));
      expect(alertsConfig).toBeDefined();
      expect(alertsConfig?.content).toContain('high-error-rate');
      expect(alertsConfig?.content).toContain('error_rate > 0.05');
      expect(alertsConfig?.content).toContain('critical');
      expect(alertsConfig?.content).toContain('slow-response');
    });
  });

  describe('Complete Monitoring Schema', () => {
    it('should generate all monitoring files for complete schema', () => {
      const workflow: Workflow = {
        workflow: {
          id: 'test',
          name: 'Test Complete Monitoring',
          version: '1.0.0',
        description: "Test workflow",
        },
        stack: {
          api: {
            type: 'backend',
            technology: 'typescript/express',
          },
          web: {
            type: 'frontend',
            technology: 'react',
          },
        },
        monitoring: {
          apm: {
            provider: 'datadog',
          },
          error_tracking: {
            provider: 'sentry',
            frontend: true,
            backend: true,
          },
          logging: {
            provider: 'winston',
            level: 'info',
            transports: [{ type: 'console' }, { type: 'file' }],
          },
          tracing: {
            provider: 'jaeger',
            sampling_rate: 0.1,
          },
          metrics: {
            tracked: ['requests', 'errors'],
            custom_metrics: [
              {
                name: 'custom_metric',
                type: 'counter',
                description: 'A custom metric',
              },
            ],
          },
          alerts: [
            {
              name: 'test-alert',
              condition: 'test > 0',
              channels: ['slack'],
            },
          ],
        },
      };

      const engine = new WorkflowEngine();
      const executionPlan = engine.analyze(workflow);

      const result = generator.generate({
        workflow,
        executionPlan,
        outputDirectory: '/test',
      });

      // Should generate multiple files
      expect(result.files.length).toBeGreaterThanOrEqual(8);

      // Backend files
      expect(result.files.find(f => f.path.includes('api/src/config/logging.ts'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('api/src/utils/logger.ts'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('api/src/config/error-tracking.ts'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('api/src/config/apm.ts'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('api/src/config/tracing.ts'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('api/src/config/metrics.ts'))).toBeDefined();

      // Frontend files
      expect(result.files.find(f => f.path.includes('web/') && f.path.includes('error-tracking.ts'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('web/') && f.path.includes('performance.ts'))).toBeDefined();

      // Shared files
      expect(result.files.find(f => f.path.includes('alerts.config.ts'))).toBeDefined();

      // All files should have absolute paths
      result.files.forEach(file => {
        expect(file.path.startsWith('/test/')).toBe(true);
      });
    });
  });
});
