/**
 * Tests for PrismaGenerator
 */

import { PrismaGenerator } from './prisma-generator';
import { WorkflowEngine } from '../../engine/workflow-engine';

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

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

  it('should have correct metadata', () => {
    expect(generator.id).toBe('prisma-database');
    expect(generator.name).toBe('Prisma Database Generator');
    expect(generator.database).toBe('prisma');
  });

  it('should generate empty result for workflow without database components', () => {
    const workflow = {
      workflow: {
        id: 'test',
        name: 'Test',
        version: '1.0.0',
        description: 'Test',
      },
      stack: {
        'web-app': {
          type: 'frontend',
          technology: 'react',
        },
      },
    };

    const engine = new WorkflowEngine();
    const executionPlan = engine.analyze(workflow as any);

    const result = generator.generate({
      workflow: workflow as any,
      executionPlan,
      outputDirectory: '/test',
    });

    expect(result.files).toHaveLength(0);
  });

  it('should generate Prisma schema with PostgreSQL', () => {
    const workflow = {
      workflow: {
        id: 'test',
        name: 'Test',
        version: '1.0.0',
        description: 'Test',
      },
      stack: {
        database: {
          type: 'database',
          technology: 'postgresql/prisma',
          tables: [
            {
              name: 'users',
              required_fields: [
                {
                  name: 'id',
                  type: 'uuid',
                  primary_key: true,
                },
                {
                  name: 'email',
                  type: 'string',
                  unique: true,
                },
                {
                  name: 'name',
                  type: 'string',
                },
              ],
            },
          ],
        },
      },
    };

    const engine = new WorkflowEngine();
    const executionPlan = engine.analyze(workflow as any);

    const result = generator.generate({
      workflow: workflow as any,
      executionPlan,
      outputDirectory: '/test',
    });

    expect(result.files.length).toBeGreaterThan(0);

    // Check schema file
    const schemaFile = result.files.find(f => f.path.includes('schema.prisma'));
    expect(schemaFile).toBeDefined();
    expect(schemaFile?.content).toContain('provider = "postgresql"');
    expect(schemaFile?.content).toContain('model Users');
    expect(schemaFile?.content).toContain('id String @id @default(uuid())');
    expect(schemaFile?.content).toContain('email String @unique');
    expect(schemaFile?.content).toContain('name String');
    expect(schemaFile?.content).toContain('createdAt DateTime @default(now())');
    expect(schemaFile?.content).toContain('updatedAt DateTime @updatedAt');
  });

  it('should generate package.json with Prisma dependencies', () => {
    const workflow = {
      workflow: {
        id: 'test',
        name: 'Test',
        version: '1.0.0',
        description: 'Test',
      },
      stack: {
        database: {
          type: 'database',
          technology: 'postgresql',
          tables: [],
        },
      },
    };

    const engine = new WorkflowEngine();
    const executionPlan = engine.analyze(workflow as any);

    const result = generator.generate({
      workflow: workflow as any,
      executionPlan,
      outputDirectory: '/test',
    });

    const pkgFile = result.files.find(f => f.path.includes('package.json'));
    expect(pkgFile).toBeDefined();

    const pkg = JSON.parse(pkgFile?.content || '{}');
    expect(pkg.dependencies['@prisma/client']).toBeDefined();
    expect(pkg.devDependencies['prisma']).toBeDefined();
    expect(pkg.scripts['db:generate']).toBe('prisma generate');
    expect(pkg.scripts['db:migrate']).toBe('prisma migrate dev');
  });

  it('should handle foreign keys correctly', () => {
    const workflow = {
      workflow: {
        id: 'test',
        name: 'Test',
        version: '1.0.0',
        description: 'Test',
      },
      stack: {
        database: {
          type: 'database',
          technology: 'postgresql/prisma',
          tables: [
            {
              name: 'users',
              required_fields: [
                {
                  name: 'id',
                  type: 'uuid',
                  primary_key: true,
                },
              ],
            },
            {
              name: 'posts',
              required_fields: [
                {
                  name: 'id',
                  type: 'uuid',
                  primary_key: true,
                },
                {
                  name: 'userId',
                  type: 'uuid',
                  foreign_key: 'users.id',
                },
              ],
            },
          ],
        },
      },
    };

    const engine = new WorkflowEngine();
    const executionPlan = engine.analyze(workflow as any);

    const result = generator.generate({
      workflow: workflow as any,
      executionPlan,
      outputDirectory: '/test',
    });

    const schemaFile = result.files.find(f => f.path.includes('schema.prisma'));
    expect(schemaFile?.content).toContain('model Posts');
    expect(schemaFile?.content).toContain('@relation');
    expect(schemaFile?.content).toContain('userId');
  });

  it('should generate migration and seed scripts', () => {
    const workflow = {
      workflow: {
        id: 'test',
        name: 'Test',
        version: '1.0.0',
        description: 'Test',
      },
      stack: {
        database: {
          type: 'database',
          technology: 'postgresql',
          tables: [],
        },
      },
    };

    const engine = new WorkflowEngine();
    const executionPlan = engine.analyze(workflow as any);

    const result = generator.generate({
      workflow: workflow as any,
      executionPlan,
      outputDirectory: '/test',
    });

    const migrationScript = result.files.find(f => f.path.includes('migrate.sh'));
    expect(migrationScript).toBeDefined();
    expect(migrationScript?.content).toContain('prisma migrate dev');

    const seedScript = result.files.find(f => f.path.includes('seed.ts'));
    expect(seedScript).toBeDefined();
    expect(seedScript?.content).toContain('PrismaClient');
  });

  it('should generate .env.example with correct database URL', () => {
    const workflow = {
      workflow: {
        id: 'test',
        name: 'Test',
        version: '1.0.0',
        description: 'Test',
      },
      stack: {
        database: {
          type: 'database',
          technology: 'mysql/prisma',
          tables: [],
        },
      },
    };

    const engine = new WorkflowEngine();
    const executionPlan = engine.analyze(workflow as any);

    const result = generator.generate({
      workflow: workflow as any,
      executionPlan,
      outputDirectory: '/test',
    });

    const envFile = result.files.find(f => f.path.includes('.env.example'));
    expect(envFile).toBeDefined();
    expect(envFile?.content).toContain('DATABASE_URL');
    expect(envFile?.content).toContain('mysql://');
  });

  it('should not overwrite package.json', () => {
    const workflow = {
      workflow: {
        id: 'test',
        name: 'Test',
        version: '1.0.0',
        description: 'Test',
      },
      stack: {
        database: {
          type: 'database',
          technology: 'postgresql',
          tables: [],
        },
      },
    };

    const engine = new WorkflowEngine();
    const executionPlan = engine.analyze(workflow as any);

    const result = generator.generate({
      workflow: workflow as any,
      executionPlan,
      outputDirectory: '/test',
    });

    const pkgFile = result.files.find(f => f.path.includes('package.json'));
    expect(pkgFile?.overwrite).toBe(false);
  });
});
