/**
 * Tests for Enhanced Feature Flags Generator
 */

import { EnhancedFeatureFlagsGenerator } from './enhanced-feature-flags-generator';
import { GeneratorContext } from '../types';
import { Workflow } from '../../types/workflow';

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

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

  it('should have correct metadata', () => {
    expect(generator.id).toBe('enhanced-feature-flags');
    expect(generator.name).toBe('Enhanced Feature Flags Generator');
    expect(generator.description).toContain('feature flag');
  });

  it('should return empty result when no feature_flags config', () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test',
        version: '1.0.0',
        name: 'Test',
        description: 'Test workflow',
      },
      stack: {
        web: {
          type: 'frontend',
          technology: 'react',
        },
      },
      stages: {
        local: {
          infrastructure: {
            databases: { primary: 'postgresql://localhost/test' },
            services: {},
          },
        },
      },
    };

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

    const result = generator.generate(context);
    expect(result.files).toHaveLength(0);
  });

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

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const configFile = result.files.find(f => f.path.includes('config/feature-flags.ts'));

      expect(configFile).toBeDefined();
      expect(configFile!.content).toContain('LaunchDarkly');
      expect(configFile!.content).toContain('LAUNCHDARKLY_SDK_KEY');
      expect(configFile!.content).toContain('ldClient');
    });
  });

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

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const configFile = result.files.find(f => f.path.includes('config/feature-flags.ts'));

      expect(configFile).toBeDefined();
      expect(configFile!.content).toContain('Split');
      expect(configFile!.content).toContain('SPLIT_API_KEY');
      expect(configFile!.content).toContain('splitClient');
    });
  });

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

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const configFile = result.files.find(f => f.path.includes('config/feature-flags.ts'));

      expect(configFile).toBeDefined();
      expect(configFile!.content).toContain('Unleash');
      expect(configFile!.content).toContain('unleash-client');
      expect(configFile!.content).toContain('UNLEASH_URL');
    });
  });

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

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const configFile = result.files.find(f => f.path.includes('config/feature-flags.ts'));

      expect(configFile).toBeDefined();
      expect(configFile!.content).toContain('CustomFeatureFlagClient');
      expect(configFile!.content).toContain('evaluateFlag');
      expect(configFile!.content).toContain('hashUserId');
    });
  });

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

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const hookFile = result.files.find(f => f.path.includes('hooks/useFeatureFlag.ts'));

      expect(hookFile).toBeDefined();
      expect(hookFile!.content).toContain('useFeatureFlag');
      expect(hookFile!.content).toContain('useFeatureFlags');
      expect(hookFile!.content).toContain('useFeatureFlagVariant');
      expect(hookFile!.content).toContain('useTrackFlagEvent');
    });

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

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const providerFile = result.files.find(f => f.path.includes('providers/FeatureFlagProvider.tsx'));

      expect(providerFile).toBeDefined();
      expect(providerFile!.content).toContain('FeatureFlagProvider');
      expect(providerFile!.content).toContain('FeatureFlagContext');
      expect(providerFile!.content).toContain('fetchFlags');
    });

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

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const componentFile = result.files.find(f => f.path.includes('components/FeatureFlag.tsx'));

      expect(componentFile).toBeDefined();
      expect(componentFile!.content).toContain('FeatureFlag');
      expect(componentFile!.content).toContain('FeatureVariant');
      expect(componentFile!.content).toContain('fallback');
    });
  });

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

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const serviceFile = result.files.find(f => f.path.includes('services/feature-flags.ts'));

      expect(serviceFile).toBeDefined();
      expect(serviceFile!.content).toContain('isFeatureEnabled');
      expect(serviceFile!.content).toContain('getAllFeatureFlags');
      expect(serviceFile!.content).toContain('getFeatureFlagsForClient');
    });

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

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const middlewareFile = result.files.find(f => f.path.includes('middleware/feature-flags.ts'));

      expect(middlewareFile).toBeDefined();
      expect(middlewareFile!.content).toContain('featureFlagMiddleware');
      expect(middlewareFile!.content).toContain('requireFeatureFlag');
      expect(middlewareFile!.content).toContain('featureFlags');
    });
  });

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

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const typesFile = result.files.find(f => f.path.includes('types/feature-flags.ts'));

      expect(typesFile).toBeDefined();
      expect(typesFile!.content).toContain('FeatureFlagKey');
      expect(typesFile!.content).toContain('new_ui');
      expect(typesFile!.content).toContain('beta_features');
      expect(typesFile!.content).toContain('FeatureFlagConfig');
    });

    it('should generate flags configuration', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0.0', name: 'Test', description: 'Test' },
        stack: {
          web: { type: 'frontend', technology: 'react' },
        },
        feature_flags: {
          provider: 'custom',
          flags: [
            {
              name: 'premium_feature',
              enabled: true,
              rollout_percentage: 50,
              rollout_strategy: 'gradual',
            },
          ],
        },
        stages: { local: { infrastructure: { databases: { primary: 'postgresql://localhost/test' }, services: {} } } },
      };

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const configFile = result.files.find(f => f.path.includes('config/flags.ts'));

      expect(configFile).toBeDefined();
      expect(configFile!.content).toContain('premium_feature');
      expect(configFile!.content).toContain('rolloutPercentage: 50');
      expect(configFile!.content).toContain("rolloutStrategy: 'gradual'");
      expect(configFile!.content).toContain('getFlagConfig');
    });
  });

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

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const rolloutFile = result.files.find(f => f.path.includes('rollout-manager.ts'));

      expect(rolloutFile).toBeDefined();
      expect(rolloutFile!.content).toContain('RolloutManager');
      expect(rolloutFile!.content).toContain('getCurrentRolloutPercentage');
      expect(rolloutFile!.content).toContain('isUserInRollout');
      expect(rolloutFile!.content).toContain('getNextRollout');
    });

    it('should not generate rollout manager when no rollout features', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0.0', name: 'Test', description: 'Test' },
        stack: {
          api: { type: 'backend', technology: 'typescript/express' },
        },
        feature_flags: {
          provider: 'launchdarkly',
          flags: [
            { name: 'simple_flag', enabled: true },
          ],
        },
        stages: { local: { infrastructure: { databases: { primary: 'postgresql://localhost/test' }, services: {} } } },
      };

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const rolloutFile = result.files.find(f => f.path.includes('rollout-manager.ts'));

      expect(rolloutFile).toBeUndefined();
    });
  });

  describe('User Segment Targeting', () => {
    it('should include user segment targeting in flag config', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0.0', name: 'Test', description: 'Test' },
        stack: {
          web: { type: 'frontend', technology: 'react' },
        },
        feature_flags: {
          provider: 'custom',
          flags: [
            {
              name: 'beta_access',
              enabled: true,
              targeting: {
                user_segments: ['beta_testers', 'internal'],
              },
            },
          ],
        },
        stages: { local: { infrastructure: { databases: { primary: 'postgresql://localhost/test' }, services: {} } } },
      };

      const result = generator.generate({ workflow, outputDirectory: '/tmp/test' , executionPlan: { workflow, componentPlans: new Map() } });
      const configFile = result.files.find(f => f.path.includes('config/flags.ts'));

      expect(configFile).toBeDefined();
      expect(configFile!.content).toContain('beta_testers');
      expect(configFile!.content).toContain('internal');
      expect(configFile!.content).toContain('userSegments');
    });
  });

  describe('Complete Feature Flags Schema', () => {
    it('should generate all files for complete feature flags configuration', () => {
      const workflow: Workflow = {
        workflow: { id: 'test', version: '1.0.0', name: 'Test', description: 'Test' },
        stack: {
          web: { type: 'frontend', technology: 'react' },
          api: { type: 'backend', technology: 'typescript/express' },
        },
        feature_flags: {
          provider: 'launchdarkly',
          flags: [
            {
              name: 'new_dashboard',
              enabled: true,
              rollout_percentage: 30,
              rollout_strategy: 'gradual',
              targeting: {
                user_segments: ['premium'],
              },
            },
          ],
        },
        stages: { local: { infrastructure: { databases: { primary: 'postgresql://localhost/test' }, services: {} } } },
      };

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

      // Backend files
      expect(result.files.find(f => f.path.includes('api/src/config/feature-flags.ts'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('api/src/services/feature-flags.ts'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('api/src/middleware/feature-flags.ts'))).toBeDefined();

      // Frontend files
      expect(result.files.find(f => f.path.includes('web/src/hooks/useFeatureFlag.ts'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('web/src/providers/FeatureFlagProvider.tsx'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('web/src/components/FeatureFlag.tsx'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('web/src/types/feature-flags.ts'))).toBeDefined();
      expect(result.files.find(f => f.path.includes('web/src/config/flags.ts'))).toBeDefined();

      // Rollout manager
      expect(result.files.find(f => f.path.includes('rollout-manager.ts'))).toBeDefined();
    });
  });
});
