import { describe, it, expect } from '@jest/globals';
import { EnvironmentGenerator } from './environment-generator';
import { GeneratorContext } from '../types';

describe('EnvironmentGenerator', () => {
  const generator = new EnvironmentGenerator();

  const mockWorkflow = {
    workflow: {
      id: 'test-workflow',
      name: 'Test Workflow',
    },
    stack: {
      'web-app': {
        type: 'frontend',
        technology: 'react',
      },
      'api': {
        type: 'backend',
        technology: 'typescript/express',
      },
      'database': {
        type: 'database',
        technology: 'postgresql',
      },
    },
    environment: {
      development: {
        'web-app': {
          VITE_API_URL: 'http://localhost:3000',
        },
        'api': {
          JWT_SECRET: 'dev-secret-key',
          DATABASE_URL: 'postgresql://localhost:5432/myapp_dev',
          NODE_ENV: 'development',
        },
        'database': {
          POSTGRES_DB: 'myapp_dev',
          POSTGRES_USER: 'dev',
          POSTGRES_PASSWORD: 'dev',
        },
      },
      production: {
        'web-app': {
          VITE_API_URL: '{{ secrets.API_URL_PROD }}',
        },
        'api': {
          JWT_SECRET: '{{ secrets.JWT_SECRET_PROD }}',
          DATABASE_URL: '{{ secrets.DATABASE_URL_PROD }}',
          NODE_ENV: 'production',
        },
      },
    },
    deployment: {
      'api': {
        environment_variables: ['JWT_SECRET', 'DATABASE_URL', 'NODE_ENV'],
      },
    },
  };

  const mockContext: GeneratorContext = {
    workflow: mockWorkflow as any,
    executionPlan: {} as any,
    outputDirectory: '/test/output',
  };

  it('should have correct metadata', () => {
    expect(generator.id).toBe('environment-config');
    expect(generator.name).toBe('Environment Configuration Generator');
    expect(generator.description).toBe('Generates environment configuration files (.env)');
  });

  it('should generate .env.example for all components', () => {
    const result = generator.generate(mockContext);

    const exampleFiles = result.files.filter(f => f.path.includes('.env.example'));
    expect(exampleFiles.length).toBe(3); // web-app, api, database

    // Check API example file
    const apiExample = exampleFiles.find(f => f.path.includes('api/.env.example'));
    expect(apiExample).toBeDefined();
    expect(apiExample?.content).toContain('JWT_SECRET');
    expect(apiExample?.content).toContain('DATABASE_URL');
    expect(apiExample?.content).toContain('NODE_ENV');
  });

  it('should generate .env.development files', () => {
    const result = generator.generate(mockContext);

    const devFiles = result.files.filter(f => f.path.includes('.env.development'));
    expect(devFiles.length).toBe(3);

    // Check API dev file
    const apiDev = devFiles.find(f => f.path.includes('api/.env.development'));
    expect(apiDev).toBeDefined();
    expect(apiDev?.content).toContain('JWT_SECRET=dev-secret-key');
    expect(apiDev?.content).toContain('DATABASE_URL=postgresql://localhost:5432/myapp_dev');
  });

  it('should generate .env.test files', () => {
    const result = generator.generate(mockContext);

    const testFiles = result.files.filter(f => f.path.includes('.env.test'));
    expect(testFiles.length).toBe(3);

    // Check API test file
    const apiTest = testFiles.find(f => f.path.includes('api/.env.test'));
    expect(apiTest).toBeDefined();
    expect(apiTest?.content).toContain('NODE_ENV=test');
    expect(apiTest?.content).toContain('test_db'); // Database URL should be modified for test
  });

  it('should process secret templates correctly', () => {
    const result = generator.generate(mockContext);

    const webAppExample = result.files.find(f => f.path.includes('web-app/.env.example'));
    expect(webAppExample).toBeDefined();
    expect(webAppExample?.content).toContain('VITE_API_URL=');
  });

  it('should group variables by category', () => {
    const result = generator.generate(mockContext);

    const apiExample = result.files.find(f => f.path.includes('api/.env.example'));
    expect(apiExample?.content).toContain('# Database');
    expect(apiExample?.content).toContain('# Authentication');
    expect(apiExample?.content).toContain('# Server');
  });

  it('should not overwrite existing env files', () => {
    const result = generator.generate(mockContext);

    const devFiles = result.files.filter(f => f.path.includes('.env.development'));
    for (const file of devFiles) {
      expect(file.overwrite).toBe(false);
    }
  });

  it('should return empty result when no environment config', () => {
    const contextWithoutEnv: GeneratorContext = {
      ...mockContext,
      workflow: {
        ...mockWorkflow,
        environment: undefined,
      } as any,
    };

    const result = generator.generate(contextWithoutEnv);
    expect(result.files.length).toBe(0);
  });
});
