/**
 * E2E Tests for Enhanced Migrations Generator
 * Generated by Bangstack
 */

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

describe('Enhanced Migrations E2E Tests', () => {
  const testOutputDir = path.join(__dirname, '../../.e2e-output/enhanced-migrations');

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

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

  it('should generate complete Prisma migration infrastructure', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test-migrations',
        version: '1.0.0',
        name: 'Test Migrations Workflow',
        description: 'Testing Prisma migrations',
      },
      stack: {},
      migrations: {
        strategy: 'prisma_migrate',
        auto_generate: true,
        version_control: {
          naming: 'timestamp',
        },
      },
    };

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

    // Verify config file
    const configPath = path.join(testOutputDir, 'api/src/config/migrations.ts');
    expect(fs.existsSync(configPath)).toBe(true);

    const configContent = fs.readFileSync(configPath, 'utf-8');
    expect(configContent).toContain('strategy: \'prisma_migrate\'');
    expect(configContent).toContain('autoGenerate: true');
    expect(configContent).toContain('naming: \'timestamp\'');

    // Verify Prisma migration file
    const prismaPath = path.join(testOutputDir, 'api/src/db/prisma-migrations.ts');
    expect(fs.existsSync(prismaPath)).toBe(true);

    const prismaContent = fs.readFileSync(prismaPath, 'utf-8');
    expect(prismaContent).toContain('PrismaMigrationRunner');
    expect(prismaContent).toContain('migrate()');
    expect(prismaContent).toContain('generateMigration');

    // Verify migration runner
    const runnerPath = path.join(testOutputDir, 'api/src/db/migration-runner.ts');
    expect(fs.existsSync(runnerPath)).toBe(true);

    // Verify scripts
    const cliPath = path.join(testOutputDir, 'api/src/scripts/migrate.ts');
    expect(fs.existsSync(cliPath)).toBe(true);
  });

  it('should generate Drizzle migration infrastructure', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test-drizzle',
        version: '1.0.0',
        name: 'Test Drizzle Migrations',
        description: 'Testing Drizzle migrations',
      },
      stack: {},
      migrations: {
        strategy: 'drizzle',
      },
    };

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

    const drizzlePath = path.join(testOutputDir, 'api/src/db/drizzle-migrations.ts');
    expect(fs.existsSync(drizzlePath)).toBe(true);

    const drizzleContent = fs.readFileSync(drizzlePath, 'utf-8');
    expect(drizzleContent).toContain('DrizzleMigrationRunner');

    // Verify drizzle config
    const configPath = path.join(testOutputDir, 'drizzle.config.ts');
    expect(fs.existsSync(configPath)).toBe(true);
  });

  it('should generate TypeORM migration infrastructure', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test-typeorm',
        version: '1.0.0',
        name: 'Test TypeORM Migrations',
        description: 'Testing TypeORM migrations',
      },
      stack: {},
      migrations: {
        strategy: 'typeorm',
      },
    };

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

    const typeormPath = path.join(testOutputDir, 'api/src/db/typeorm-migrations.ts');
    expect(fs.existsSync(typeormPath)).toBe(true);

    const typeormContent = fs.readFileSync(typeormPath, 'utf-8');
    expect(typeormContent).toContain('TypeORMMigrationRunner');
    expect(typeormContent).toContain('runMigrations');
    expect(typeormContent).toContain('undoLastMigration');
  });

  it('should generate Knex migration infrastructure', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test-knex',
        version: '1.0.0',
        name: 'Test Knex Migrations',
        description: 'Testing Knex migrations',
      },
      stack: {},
      migrations: {
        strategy: 'knex',
      },
    };

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

    const knexPath = path.join(testOutputDir, 'api/src/db/knex-migrations.ts');
    expect(fs.existsSync(knexPath)).toBe(true);

    const knexContent = fs.readFileSync(knexPath, 'utf-8');
    expect(knexContent).toContain('KnexMigrationRunner');
    expect(knexContent).toContain('migrate.latest');

    // Verify knexfile
    const knexfilePath = path.join(testOutputDir, 'knexfile.ts');
    expect(fs.existsSync(knexfilePath)).toBe(true);

    const knexfileContent = fs.readFileSync(knexfilePath, 'utf-8');
    expect(knexfileContent).toContain('development');
    expect(knexfileContent).toContain('production');
  });

  it('should generate custom migration framework', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test-custom',
        version: '1.0.0',
        name: 'Test Custom Migrations',
        description: 'Testing custom migrations',
      },
      stack: {},
      migrations: {
        strategy: 'custom',
      },
    };

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

    const customPath = path.join(testOutputDir, 'api/src/db/custom-migrations.ts');
    expect(fs.existsSync(customPath)).toBe(true);

    const customContent = fs.readFileSync(customPath, 'utf-8');
    expect(customContent).toContain('CustomMigrationRunner');
    expect(customContent).toContain('loadMigrations');
  });

  it('should generate migration validator', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test-validator',
        version: '1.0.0',
        name: 'Test Migration Validator',
        description: 'Testing migration validator',
      },
      stack: {},
      migrations: {
        strategy: 'prisma_migrate',
      },
    };

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

    const validatorPath = path.join(testOutputDir, 'api/src/db/migration-validator.ts');
    expect(fs.existsSync(validatorPath)).toBe(true);

    const validatorContent = fs.readFileSync(validatorPath, 'utf-8');
    expect(validatorContent).toContain('MigrationValidator');
    expect(validatorContent).toContain('validate()');
    expect(validatorContent).toContain('validateFileName');
  });

  it('should generate data migration template', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test-data-migration',
        version: '1.0.0',
        name: 'Test Data Migration',
        description: 'Testing data migration template',
      },
      stack: {},
      migrations: {
        strategy: 'prisma_migrate',
      },
    };

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

    const templatePath = path.join(testOutputDir, 'migrations/data_migration_template.ts.template');
    expect(fs.existsSync(templatePath)).toBe(true);

    const templateContent = fs.readFileSync(templatePath, 'utf-8');
    expect(templateContent).toContain('Data Migration Template');
    expect(templateContent).toContain('async up()');
    expect(templateContent).toContain('async down()');
  });

  it('should generate rollback script', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test-rollback',
        version: '1.0.0',
        name: 'Test Rollback',
        description: 'Testing rollback script',
      },
      stack: {},
      migrations: {
        strategy: 'prisma_migrate',
      },
    };

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

    const rollbackPath = path.join(testOutputDir, 'api/src/scripts/rollback.ts');
    expect(fs.existsSync(rollbackPath)).toBe(true);

    const rollbackContent = fs.readFileSync(rollbackPath, 'utf-8');
    expect(rollbackContent).toContain('migrationRunner.rollback()');
    expect(rollbackContent).toContain('WARNING: Rolling back in PRODUCTION');
  });

  it('should generate migration CLI', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test-cli',
        version: '1.0.0',
        name: 'Test CLI',
        description: 'Testing migration CLI',
      },
      stack: {},
      migrations: {
        strategy: 'prisma_migrate',
      },
    };

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

    const cliPath = path.join(testOutputDir, 'api/src/scripts/migrate.ts');
    expect(fs.existsSync(cliPath)).toBe(true);

    const cliContent = fs.readFileSync(cliPath, 'utf-8');
    expect(cliContent).toContain('#!/usr/bin/env node');
    expect(cliContent).toContain('commander');
    expect(cliContent).toContain('.command(\'up\')');
    expect(cliContent).toContain('.command(\'down\')');
    expect(cliContent).toContain('.command(\'status\')');
    expect(cliContent).toContain('.command(\'validate\')');
  });

  it('should handle sequential version naming', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test-sequential',
        version: '1.0.0',
        name: 'Test Sequential Versioning',
        description: 'Testing sequential version naming',
      },
      stack: {},
      migrations: {
        strategy: 'prisma_migrate',
        version_control: {
          naming: 'sequential',
        },
      },
    };

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

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

    const configContent = fs.readFileSync(configPath, 'utf-8');
    expect(configContent).toContain('naming: \'sequential\'');
  });

  it('should handle auto_generate false', async () => {
    const workflow: Workflow = {
      workflow: {
        id: 'test-no-auto',
        version: '1.0.0',
        name: 'Test No Auto Generate',
        description: 'Testing auto generate false',
      },
      stack: {},
      migrations: {
        strategy: 'prisma_migrate',
        auto_generate: false,
      },
    };

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

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

    const configContent = fs.readFileSync(configPath, 'utf-8');
    expect(configContent).toContain('autoGenerate: false');
  });
});
