/**
 * E2E Test: Enhanced Feature Flags Generator
 *
 * This test verifies that the enhanced feature flags generator actually writes
 * all expected feature flag 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 Feature Flags Generator', () => {
  const testOutputDir = path.join(__dirname, '../../.e2e-output/enhanced-feature-flags');
  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 feature flag files for complete schema', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'e2e-feature-flags-test',
        version: '1.0.0',
        name: 'E2E Feature Flags Test',
        description: 'Testing enhanced feature flags generator E2E',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
          config: { port: 5173 },
        },
        api: {
          type: 'backend',
          technology: 'typescript/express',
          config: { port: 3000 },
        },
      },
      feature_flags: {
        provider: 'launchdarkly',
        flags: [
          {
            name: 'new_dashboard',
            enabled: true,
            rollout_percentage: 50,
            rollout_strategy: 'gradual',
            targeting: {
              user_segments: ['beta_testers'],
            },
          },
          {
            name: 'premium_features',
            enabled: false,
          },
        ],
      },
      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/src/config/feature-flags.ts',
      'api/src/services/feature-flags.ts',
      'api/src/middleware/feature-flags.ts',
      'web/src/hooks/useFeatureFlag.ts',
      'web/src/providers/FeatureFlagProvider.tsx',
      'web/src/components/FeatureFlag.tsx',
      'web/src/types/feature-flags.ts',
      'web/src/config/flags.ts',
      'api/src/utils/rollout-manager.ts',
    ];

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

  it('should generate LaunchDarkly configuration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'launchdarkly-test',
        version: '1.0.0',
        name: 'LaunchDarkly Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
        },
      },
      feature_flags: {
        provider: 'launchdarkly',
        flags: [{ name: 'test_flag', enabled: true }],
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the config file
    const configPath = path.join(testOutputDir, 'api/src/config/feature-flags.ts');
    expect(fs.existsSync(configPath)).toBe(true);

    const config = fs.readFileSync(configPath, 'utf-8');

    // Verify LaunchDarkly configuration
    expect(config).toContain('LaunchDarkly');
    expect(config).toContain('LAUNCHDARKLY_SDK_KEY');
    expect(config).toContain('ldClient');
    expect(config).toContain('evaluateFlag');
    expect(config).toContain('evaluateAllFlags');
  });

  it('should generate Split configuration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'split-test',
        version: '1.0.0',
        name: 'Split Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
        },
      },
      feature_flags: {
        provider: 'split',
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the config file
    const configPath = path.join(testOutputDir, 'api/src/config/feature-flags.ts');
    expect(fs.existsSync(configPath)).toBe(true);

    const config = fs.readFileSync(configPath, 'utf-8');

    // Verify Split configuration
    expect(config).toContain('Split');
    expect(config).toContain('SPLIT_API_KEY');
    expect(config).toContain('splitClient');
    expect(config).toContain('getTreatment');
  });

  it('should generate Unleash configuration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'unleash-test',
        version: '1.0.0',
        name: 'Unleash Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
        },
      },
      feature_flags: {
        provider: 'unleash',
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the config file
    const configPath = path.join(testOutputDir, 'api/src/config/feature-flags.ts');
    expect(fs.existsSync(configPath)).toBe(true);

    const config = fs.readFileSync(configPath, 'utf-8');

    // Verify Unleash configuration
    expect(config).toContain('Unleash');
    expect(config).toContain('unleash-client');
    expect(config).toContain('UNLEASH_URL');
    expect(config).toContain('isEnabled');
    expect(config).toContain('getVariant');
  });

  it('should generate custom feature flag configuration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'custom-test',
        version: '1.0.0',
        name: 'Custom Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
        },
      },
      feature_flags: {
        provider: 'custom',
        flags: [
          {
            name: 'beta_feature',
            enabled: true,
            rollout_percentage: 25,
          },
        ],
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the config file
    const configPath = path.join(testOutputDir, 'api/src/config/feature-flags.ts');
    expect(fs.existsSync(configPath)).toBe(true);

    const config = fs.readFileSync(configPath, 'utf-8');

    // Verify custom configuration
    expect(config).toContain('CustomFeatureFlagClient');
    expect(config).toContain('hashUserId');
    expect(config).toContain('rolloutPercentage');
  });

  it('should generate React feature flag hook', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'hook-test',
        version: '1.0.0',
        name: 'Hook Test',
        description: 'Test workflow',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
        },
      },
      feature_flags: {
        provider: 'launchdarkly',
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the hook file
    const hookPath = path.join(testOutputDir, 'web/src/hooks/useFeatureFlag.ts');
    expect(fs.existsSync(hookPath)).toBe(true);

    const hook = fs.readFileSync(hookPath, 'utf-8');

    // Verify hook exports
    expect(hook).toContain('useFeatureFlag');
    expect(hook).toContain('useFeatureFlags');
    expect(hook).toContain('useFeatureFlagVariant');
    expect(hook).toContain('useTrackFlagEvent');
    expect(hook).toContain('FeatureFlagContext');
  });

  it('should generate feature flag provider component', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'provider-test',
        version: '1.0.0',
        name: 'Provider Test',
        description: 'Test workflow',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
        },
      },
      feature_flags: {
        provider: 'split',
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the provider file
    const providerPath = path.join(testOutputDir, 'web/src/providers/FeatureFlagProvider.tsx');
    expect(fs.existsSync(providerPath)).toBe(true);

    const provider = fs.readFileSync(providerPath, 'utf-8');

    // Verify provider implementation
    expect(provider).toContain('FeatureFlagProvider');
    expect(provider).toContain('FeatureFlagContext');
    expect(provider).toContain('fetchFlags');
    expect(provider).toContain('trackEvent');
  });

  it('should generate feature flag component wrapper', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'component-test',
        version: '1.0.0',
        name: 'Component Test',
        description: 'Test workflow',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
        },
      },
      feature_flags: {
        provider: 'unleash',
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the component file
    const componentPath = path.join(testOutputDir, 'web/src/components/FeatureFlag.tsx');
    expect(fs.existsSync(componentPath)).toBe(true);

    const component = fs.readFileSync(componentPath, 'utf-8');

    // Verify component exports
    expect(component).toContain('FeatureFlag');
    expect(component).toContain('FeatureVariant');
    expect(component).toContain('fallback');
    expect(component).toContain('invert');
  });

  it('should generate backend feature flag service', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'service-test',
        version: '1.0.0',
        name: 'Service Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
        },
      },
      feature_flags: {
        provider: 'launchdarkly',
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the service file
    const servicePath = path.join(testOutputDir, 'api/src/services/feature-flags.ts');
    expect(fs.existsSync(servicePath)).toBe(true);

    const service = fs.readFileSync(servicePath, 'utf-8');

    // Verify service methods
    expect(service).toContain('isFeatureEnabled');
    expect(service).toContain('getAllFeatureFlags');
    expect(service).toContain('getFeatureFlagsForClient');
  });

  it('should generate feature flag middleware', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'middleware-test',
        version: '1.0.0',
        name: 'Middleware Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
        },
      },
      feature_flags: {
        provider: 'custom',
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the middleware file
    const middlewarePath = path.join(testOutputDir, 'api/src/middleware/feature-flags.ts');
    expect(fs.existsSync(middlewarePath)).toBe(true);

    const middleware = fs.readFileSync(middlewarePath, 'utf-8');

    // Verify middleware functions
    expect(middleware).toContain('featureFlagMiddleware');
    expect(middleware).toContain('requireFeatureFlag');
    expect(middleware).toContain('.featureFlags');
  });

  it('should generate flag types and configuration', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'types-test',
        version: '1.0.0',
        name: 'Types Test',
        description: 'Test workflow',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
        },
      },
      feature_flags: {
        provider: 'custom',
        flags: [
          { name: 'new_ui', enabled: true },
          { name: 'dark_mode', enabled: false },
        ],
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the types file
    const typesPath = path.join(testOutputDir, 'web/src/types/feature-flags.ts');
    expect(fs.existsSync(typesPath)).toBe(true);

    const types = fs.readFileSync(typesPath, 'utf-8');
    expect(types).toContain('FeatureFlagKey');
    expect(types).toContain('new_ui');
    expect(types).toContain('dark_mode');

    // Read the config file
    const configPath = path.join(testOutputDir, 'web/src/config/flags.ts');
    expect(fs.existsSync(configPath)).toBe(true);

    const config = fs.readFileSync(configPath, 'utf-8');
    expect(config).toContain('new_ui');
    expect(config).toContain('dark_mode');
    expect(config).toContain('getFlagConfig');
  });

  it('should generate rollout manager for gradual rollouts', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'rollout-test',
        version: '1.0.0',
        name: 'Rollout Test',
        description: 'Test workflow',
      },
      stack: {
        api: {
          type: 'backend',
          technology: 'typescript/express',
        },
      },
      feature_flags: {
        provider: 'custom',
        flags: [
          {
            name: 'gradual_feature',
            enabled: true,
            rollout_percentage: 50,
            rollout_strategy: 'gradual',
            schedule: [
              { date: '2024-01-01', percentage: 10 },
              { date: '2024-02-01', percentage: 100 },
            ],
          },
        ],
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the rollout manager file
    const rolloutPath = path.join(testOutputDir, 'api/src/utils/rollout-manager.ts');
    expect(fs.existsSync(rolloutPath)).toBe(true);

    const rollout = fs.readFileSync(rolloutPath, 'utf-8');

    // Verify rollout manager
    expect(rollout).toContain('RolloutManager');
    expect(rollout).toContain('getCurrentRolloutPercentage');
    expect(rollout).toContain('isUserInRollout');
    expect(rollout).toContain('getNextRollout');
    expect(rollout).toContain('hashUserId');
  });

  it('should handle user segment targeting', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'targeting-test',
        version: '1.0.0',
        name: 'Targeting Test',
        description: 'Test workflow',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
        },
      },
      feature_flags: {
        provider: 'custom',
        flags: [
          {
            name: 'premium_feature',
            enabled: true,
            targeting: {
              user_segments: ['premium', 'enterprise'],
            },
          },
        ],
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    // Read the flags config
    const configPath = path.join(testOutputDir, 'web/src/config/flags.ts');
    expect(fs.existsSync(configPath)).toBe(true);

    const config = fs.readFileSync(configPath, 'utf-8');
    expect(config).toContain('premium');
    expect(config).toContain('enterprise');
    expect(config).toContain('userSegments');
  });
});
