/**
 * E2E Test: Enhanced Performance Generator
 *
 * This test verifies that the enhanced performance generator actually writes
 * all expected performance optimization files to disk with correct content.
 */

import * as fs from 'fs';
import * as path from 'path';
import '../generators/index'; // Ensure all generators are registered
import { GenerationOrchestrator } from '../generators/generation-orchestrator';
import { Workflow } from '../types/workflow';

describe('E2E: Enhanced Performance Generator', () => {
  const testOutputDir = path.join(__dirname, '../../.e2e-output/enhanced-performance');
  let orchestrator: GenerationOrchestrator;

  beforeEach(() => {
    // Clean up test directory before each test
    if (fs.existsSync(testOutputDir)) {
      fs.rmSync(testOutputDir, { recursive: true, force: true });
    }

    orchestrator = new GenerationOrchestrator();
  });

  afterEach(() => {
    // Clean up test directory after each test
    if (fs.existsSync(testOutputDir)) {
      fs.rmSync(testOutputDir, { recursive: true, force: true });
    }
  });

  it('should generate all performance files for complete performance schema', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'e2e-performance-test',
        version: '1.0.0',
        name: 'E2E Performance Test',
        description: 'Testing enhanced performance generator E2E',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
        web: {
          type: 'frontend',
          technology: 'react',
          config: { port: 5173 },
        },
      },
      performance: {
        frontend: {
          code_splitting: 'route_based',
          lazy_loading: true,
          tree_shaking: true,
          bundle_budget: {
            max_initial: '200kb',
            max_total: '1mb',
          },
        },
        backend: {
          caching: {
            strategy: 'redis',
            ttl: 3600,
            cache_keys: ['user', 'posts'],
          },
          connection_pooling: {
            min: 5,
            max: 20,
            idle_timeout: 10000,
          },
          query_optimization: true,
        },
        cdn: {
          provider: 'cloudflare',
          assets: ['*.js', '*.css', '*.png'],
          cache_ttl: 86400,
        },
        database: {
          read_replicas: 2,
          sharding: {
            strategy: 'by_tenant',
            shard_count: 4,
          },
          indexing_strategy: 'auto',
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    // Generate code
    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Verify files were generated
    expect(_result.files.length).toBeGreaterThan(0);

    // Define expected files
    const expectedFiles = [
      'web/vite.performance.config.ts',
      'web/src/utils/code-splitting.tsx',
      'web/src/utils/lazy-loading.tsx',
      'web/scripts/analyze-bundle.ts',
      'api/src/config/caching.ts',
      'api/src/config/database-pool.ts',
      'api/src/utils/query-optimization.ts',
      'api/src/config/read-replicas.ts',
      'api/src/config/sharding.ts',
      'api/src/utils/indexing.ts',
      'cdn.config.ts',
    ];

    // Verify each expected file exists
    expectedFiles.forEach(expectedFile => {
      const fullPath = path.join(testOutputDir, expectedFile);
      expect(fs.existsSync(fullPath)).toBe(true);
    });
  });

  it('should generate bundler configuration with correct code splitting strategy', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'bundler-test',
        version: '1.0.0',
        name: 'Bundler Test',
        description: 'Test workflow',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
          config: { port: 5173 },
        },
      },
      performance: {
        frontend: {
          code_splitting: 'component_based',
          bundle_budget: {
            max_initial: '300kb',
          },
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read the generated bundler config
    const bundlerConfigPath = path.join(testOutputDir, 'web/vite.performance.config.ts');
    expect(fs.existsSync(bundlerConfigPath)).toBe(true);

    const bundlerConfig = fs.readFileSync(bundlerConfigPath, 'utf-8');

    // Verify bundler configuration
    expect(bundlerConfig).toContain('component_based');
    expect(bundlerConfig).toContain('300kb');
    expect(bundlerConfig).toContain('Component-based code splitting');
  });

  it('should generate Redis caching configuration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'caching-test',
        version: '1.0.0',
        name: 'Caching Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      performance: {
        backend: {
          caching: {
            strategy: 'redis',
            ttl: 7200,
            cache_keys: ['products', 'categories'],
          },
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read the generated caching config
    const cachingPath = path.join(testOutputDir, 'api/src/config/caching.ts');
    expect(fs.existsSync(cachingPath)).toBe(true);

    const cachingConfig = fs.readFileSync(cachingPath, 'utf-8');

    // Verify caching setup
    expect(cachingConfig).toContain('redis');
    expect(cachingConfig).toContain('createClient');
    expect(cachingConfig).toContain('ttl: 7200');
    expect(cachingConfig).toContain('getCache');
    expect(cachingConfig).toContain('setCache');
    expect(cachingConfig).toContain('cached');
  });

  it('should generate connection pooling configuration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'pooling-test',
        version: '1.0.0',
        name: 'Pooling Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      performance: {
        backend: {
          connection_pooling: {
            min: 10,
            max: 50,
            idle_timeout: 15000,
          },
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read connection pooling config
    const poolingPath = path.join(testOutputDir, 'api/src/config/database-pool.ts');
    expect(fs.existsSync(poolingPath)).toBe(true);

    const poolingConfig = fs.readFileSync(poolingPath, 'utf-8');

    // Verify pooling configuration
    expect(poolingConfig).toContain('min: 10');
    expect(poolingConfig).toContain('max: 50');
    expect(poolingConfig).toContain('idleTimeoutMillis: 15000');
    expect(poolingConfig).toContain('Pool');
    expect(poolingConfig).toContain('transaction');
  });

  it('should generate CDN configuration for Cloudflare', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'cdn-test',
        version: '1.0.0',
        name: 'CDN Test',
        description: 'Test workflow',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
          config: { port: 5173 },
        },
      },
      performance: {
        cdn: {
          provider: 'cloudflare',
          assets: ['*.js', '*.css', '*.woff2'],
          cache_ttl: 604800,
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read CDN config
    const cdnPath = path.join(testOutputDir, 'cdn.config.ts');
    expect(fs.existsSync(cdnPath)).toBe(true);

    const cdnConfig = fs.readFileSync(cdnPath, 'utf-8');

    // Verify CDN configuration
    expect(cdnConfig).toContain('cloudflare');
    expect(cdnConfig).toContain('setCloudflareCacheHeaders');
    expect(cdnConfig).toContain('purgeCloudflarCache');
    expect(cdnConfig).toContain('cacheTTL: 604800');
    expect(cdnConfig).toContain('*.woff2');
  });

  it('should generate read replica configuration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'replica-test',
        version: '1.0.0',
        name: 'Read Replica Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      performance: {
        database: {
          read_replicas: 3,
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read replica config
    const replicaPath = path.join(testOutputDir, 'api/src/config/read-replicas.ts');
    expect(fs.existsSync(replicaPath)).toBe(true);

    const replicaConfig = fs.readFileSync(replicaPath, 'utf-8');

    // Verify replica configuration
    expect(replicaConfig).toContain('primaryPool');
    expect(replicaConfig).toContain('DB_REPLICA_1_HOST');
    expect(replicaConfig).toContain('DB_REPLICA_2_HOST');
    expect(replicaConfig).toContain('DB_REPLICA_3_HOST');
    expect(replicaConfig).toContain('readQuery');
    expect(replicaConfig).toContain('writeQuery');
    expect(replicaConfig).toContain('round-robin');
  });

  it('should generate sharding configuration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'sharding-test',
        version: '1.0.0',
        name: 'Sharding Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      performance: {
        database: {
          sharding: {
            strategy: 'by_hash',
            shard_count: 8,
          },
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
      });

    // Read sharding config
    const shardingPath = path.join(testOutputDir, 'api/src/config/sharding.ts');
    expect(fs.existsSync(shardingPath)).toBe(true);

    const shardingConfig = fs.readFileSync(shardingPath, 'utf-8');

    // Verify sharding configuration
    expect(shardingConfig).toContain('by_hash');
    expect(shardingConfig).toContain('shardCount: 8');
    expect(shardingConfig).toContain('getShardByHash');
    expect(shardingConfig).toContain('queryAllShards');
  });

  it('should generate lazy loading utilities', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'lazy-loading-test',
        version: '1.0.0',
        name: 'Lazy Loading Test',
        description: 'Test workflow',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
          config: { port: 5173 },
        },
      },
      performance: {
        frontend: {
          lazy_loading: true,
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

    const _result = await orchestrator.generate(workflow, {
      outputDirectory: testOutputDir,
      dryRun: false,
      verbose: false,
    });

    // Read lazy loading utilities
    const lazyLoadingPath = path.join(testOutputDir, 'web/src/utils/lazy-loading.tsx');
    expect(fs.existsSync(lazyLoadingPath)).toBe(true);

    const lazyLoading = fs.readFileSync(lazyLoadingPath, 'utf-8');

    // Verify lazy loading utilities
    expect(lazyLoading).toContain('useLazyImage');
    expect(lazyLoading).toContain('LazyImage');
    expect(lazyLoading).toContain('useLazyComponent');
    expect(lazyLoading).toContain('IntersectionObserver');
    expect(lazyLoading).toContain('preloadResource');
    expect(lazyLoading).toContain('prefetchRoute');
  });
});
