/**
 * E2E Test: Enhanced Testing Generator
 *
 * This test verifies that the enhanced testing generator actually writes
 * all expected test configuration 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 Testing Generator', () => {
  const testOutputDir = path.join(__dirname, '../../.e2e-output/enhanced-testing');
  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 test files for enhanced testing schema', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'e2e-enhanced-testing',
        version: '1.0.0',
        name: 'E2E Enhanced Testing',
        description: 'Testing enhanced testing generator E2E',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
        web: {
          type: 'frontend',
          technology: 'react',
          config: { port: 5173 },
        },
      },
      testing: {
        frameworks: {
          unit: {
            framework: 'vitest',
            config: { coverage: true },
          },
          e2e: {
            framework: 'playwright',
            browsers: ['chromium', 'firefox'],
          },
        },
        coverage: {
          threshold: {
            global: {
              statements: 80,
              branches: 75,
              functions: 80,
              lines: 80,
            },
          },
        },
        database: {
          strategy: 'testcontainers',
          reset_strategy: 'truncate',
        },
        ci_cd: {
          provider: 'github_actions',
          test_on_pr: true,
          test_requirements: {
            require_passing: true,
            minimum_coverage: 80,
          },
        },
      },
      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 = [
      'api/vitest.config.ts',
      'api/src/test/setup.ts',
      'api/src/test/helpers/database.ts',
      'web/playwright.config.ts',
      '.github/workflows/test.yml',
    ];

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

  it('should generate Vitest config with correct coverage thresholds', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'coverage-test',
        version: '1.0.0',
        name: 'Coverage Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      testing: {
        frameworks: {
          unit: {
            framework: 'vitest',
            config: { coverage: true },
          },
        },
        coverage: {
          threshold: {
            global: {
              statements: 85,
              branches: 80,
              functions: 85,
              lines: 85,
            },
          },
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

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

    const vitestConfig = fs.readFileSync(vitestConfigPath, 'utf-8');

    // Verify coverage thresholds are correctly set
    expect(vitestConfig).toContain('statements: 85');
    expect(vitestConfig).toContain('branches: 80');
    expect(vitestConfig).toContain('functions: 85');
    expect(vitestConfig).toContain('lines: 85');
    expect(vitestConfig).toContain('defineConfig');
    expect(vitestConfig).toContain("provider: 'v8'");
  });

  it('should generate testcontainers database helpers', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'db-test',
        version: '1.0.0',
        name: 'Database Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      testing: {
        frameworks: {
          unit: { framework: 'vitest' },
        },
        database: {
          strategy: 'testcontainers',
          reset_strategy: 'truncate',
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the generated database helper
    const dbHelperPath = path.join(testOutputDir, 'api/src/test/helpers/database.ts');
    expect(fs.existsSync(dbHelperPath)).toBe(true);

    const dbHelper = fs.readFileSync(dbHelperPath, 'utf-8');

    // Verify testcontainers setup
    expect(dbHelper).toContain('testcontainers');
    expect(dbHelper).toContain('PostgreSqlContainer');
    expect(dbHelper).toContain('setupTestDatabase');
    expect(dbHelper).toContain('teardownTestDatabase');
    expect(dbHelper).toContain('truncateAllTables');
  });

  it('should generate Playwright config with specified browsers', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'playwright-test',
        version: '1.0.0',
        name: 'Playwright Test',
        description: 'Test workflow',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
          config: { port: 5173 },
        },
      },
      testing: {
        frameworks: {
          e2e: {
            framework: 'playwright',
            browsers: ['chromium', 'firefox', 'webkit'],
          },
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the generated playwright config
    const playwrightConfigPath = path.join(testOutputDir, 'web/playwright.config.ts');
    expect(fs.existsSync(playwrightConfigPath)).toBe(true);

    const playwrightConfig = fs.readFileSync(playwrightConfigPath, 'utf-8');

    // Verify all browsers are configured
    expect(playwrightConfig).toContain('chromium');
    expect(playwrightConfig).toContain('firefox');
    expect(playwrightConfig).toContain('webkit');
    expect(playwrightConfig).toContain('@playwright/test');
    expect(playwrightConfig).toContain('defineConfig');
  });

  it('should generate GitHub Actions workflow with coverage enforcement', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'ci-test',
        version: '1.0.0',
        name: 'CI Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      testing: {
        frameworks: {
          unit: { framework: 'vitest' },
        },
        ci_cd: {
          provider: 'github_actions',
          test_on_pr: true,
          test_requirements: {
            require_passing: true,
            minimum_coverage: 80,
          },
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the generated GitHub Actions workflow
    const ghActionsPath = path.join(testOutputDir, '.github/workflows/test.yml');
    expect(fs.existsSync(ghActionsPath)).toBe(true);

    const ghActions = fs.readFileSync(ghActionsPath, 'utf-8');

    // Verify CI/CD configuration
    expect(ghActions).toContain('pull_request');
    expect(ghActions).toContain('Test');
    expect(ghActions).toMatch(/name:\s*Test/);
  });

  it('should not generate files for legacy testing format', async () => {
    const workflow: any = {
      workflow: {
        id: 'legacy-test',
        version: '1.0.0',
        name: 'Legacy Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      testing: {
        // Legacy format - should be skipped
        unit_tests: [
          {
            component: 'api',
            scenarios: ['test'],
          },
        ],
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Enhanced testing generator should not create vitest.config.ts for legacy format
    const vitestConfigPath = path.join(testOutputDir, 'api/vitest.config.ts');
    // Legacy backend test generator might create files, but not enhanced generator
    // Check that if vitest.config.ts exists, it's from the legacy generator
    if (fs.existsSync(vitestConfigPath)) {
      const config = fs.readFileSync(vitestConfigPath, 'utf-8');
      // Enhanced generator has specific markers like coverage thresholds object
      // Legacy might not have these specific patterns
      expect(config).not.toContain('Strategy: testcontainers');
    }
  });
});
