/**
 * Integration Tests for Documentation Generation
 * Tests the full documentation generation flow end-to-end
 */

import * as fs from 'fs';
import * as path from 'path';
import { MarkdownDocumentationGenerator } from './markdown-generator';
import { GeneratorContext } from '../types';
import { Workflow } from '../../types/workflow';

describe('Documentation Integration Tests', () => {
  const testOutputDir = '/tmp/bangstack-docs-integration-test';

  beforeEach(() => {
    // Clean up test directory
    if (fs.existsSync(testOutputDir)) {
      fs.rmSync(testOutputDir, { recursive: true });
    }
    fs.mkdirSync(testOutputDir, { recursive: true });
  });

  afterEach(() => {
    // Clean up after tests
    if (fs.existsSync(testOutputDir)) {
      fs.rmSync(testOutputDir, { recursive: true });
    }
  });

  it('should generate all documentation types from intents', async () => {
    const generator = new MarkdownDocumentationGenerator();

    const workflow: Workflow = {
      workflow: {
        id: 'integration-test',
        name: 'Integration Test App',
        version: '1.0.0',
        description: 'Test application for integration testing',
      },
      stack: {},
    };

    const context: GeneratorContext = {
      workflow,
      extendedWorkflow: {
        technology: {
          frontend: {
            framework: 'react',
            language: 'typescript',
            styling: 'tailwind',
          },
          backend: {
            framework: 'express',
            language: 'typescript',
            orm: 'prisma',
          },
                 
          database: 'postgresql',
        },
        models: {
          User: {
            description: 'Application user',
            fields: {
              name: { type: 'string', required: true, unique: false, system_field: false, exclude_from_forms: false },
              email: { type: 'string', required: true, unique: false, system_field: false, exclude_from_forms: false },
            },
            timestamps: true,
      soft_delete: false,
          },
        },
        api: {
          base_path: '/api',
          endpoints: [
            { path: '/users', method: 'GET', component: 'users', auth: 'none' as const, description: 'Get all users',
            },
          ],
        },
        auth: {
          enabled: true,
          provider: 'clerk',
        },
        documentation: {
          intents: [
            { type: 'setup_guide', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false },
            { type: 'api_reference', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false },
            { type: 'tutorial', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false, topics: ['create_endpoint'] },
            { type: 'architecture', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false },
            { type: 'best_practices', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false },
            { type: 'troubleshooting', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false },
          ],
        },
      },
      outputDirectory: testOutputDir,
      executionPlan: { workflow, componentPlans: new Map() },
    };

    const result = await generator.generate(context);

    // Should generate 7 files (6 intents + 1 index)
    expect(result.files.length).toBe(7);

    // Write files to disk
    for (const file of result.files) {
      const dir = path.dirname(file.path);
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
      }
      fs.writeFileSync(file.path, file.content);
    }

    // Verify all expected files were created
    const docsDir = path.join(testOutputDir, 'docs');
    expect(fs.existsSync(docsDir)).toBe(true);

    const expectedFiles = [
      'setup_guide.md',
      'api_reference.md',
      'tutorial.md',
      'architecture.md',
      'best_practices.md',
      'troubleshooting.md',
      'README.md',
    ];

    for (const filename of expectedFiles) {
      const filepath = path.join(docsDir, filename);
      expect(fs.existsSync(filepath)).toBe(true);

      const content = fs.readFileSync(filepath, 'utf-8');
      expect(content.length).toBeGreaterThan(0);
    }
  });

  it('should generate technology-specific documentation', async () => {
    const generator = new MarkdownDocumentationGenerator();

    const testWorkflow = {
      workflow: {
        id: 'tech-test',
        name: 'Tech Test',
        version: '1.0.0',
        description: 'Test',
      },
      stack: {},
    };

    const context: GeneratorContext = {
      workflow: testWorkflow,
      extendedWorkflow: {
        technology: {
          backend: {
            framework: 'flask',
            language: 'python',
          },
        },
        documentation: {
          intents: [
            { type: 'tutorial', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false,
              topics: ['create_endpoint'],
            },
            { type: 'best_practices', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false,
            },
          ],
        },
      },
      outputDirectory: testOutputDir,
      executionPlan: { workflow: testWorkflow, componentPlans: new Map() },
    };

    const result = await generator.generate(context);

    // Write files
    for (const file of result.files) {
      const dir = path.dirname(file.path);
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
      }
      fs.writeFileSync(file.path, file.content);
    }

    // Check tutorial has Python/Flask content
    const tutorialPath = path.join(testOutputDir, 'docs', 'tutorial.md');
    const tutorialContent = fs.readFileSync(tutorialPath, 'utf-8');
    expect(tutorialContent).toContain('Blueprint');
    expect(tutorialContent).toContain('routes/items.py');
    expect(tutorialContent).toContain('flask');

    // Check best practices has Python content
    const bestPracticesPath = path.join(testOutputDir, 'docs', 'best_practices.md');
    const bestPracticesContent = fs.readFileSync(bestPracticesPath, 'utf-8');
    expect(bestPracticesContent).toContain('Python/Flask');
    expect(bestPracticesContent).toContain('PEP 8');
  });

  it('should respect overwrite policies', async () => {
    const generator = new MarkdownDocumentationGenerator();

    const testWorkflow = {
      workflow: {
        id: 'overwrite-test',
        name: 'Overwrite Test',
        version: '1.0.0',
        description: 'Test',
      },
      stack: {},
    };

    const context: GeneratorContext = {
      workflow: testWorkflow,
      extendedWorkflow: {
        documentation: {
          intents: [
            { type: 'setup_guide', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false },
            { type: 'api_reference', audience: 'developer', overwrite: 'never', includeExamples: false, includeCommonIssues: false },
          ],
        },
      },
      outputDirectory: testOutputDir,
      executionPlan: { workflow: testWorkflow, componentPlans: new Map() },
    };

    const result = await generator.generate(context);

    // Check overwrite flags
    const setupGuide = result.files.find(f => f.path.includes('setup_guide'));
    const apiRef = result.files.find(f => f.path.includes('api_reference'));

    expect(setupGuide?.overwrite).toBe(true);
    expect(apiRef?.overwrite).toBe(false);
  });

  it('should generate custom output paths when specified', async () => {
    const generator = new MarkdownDocumentationGenerator();

    const testWorkflow = {
      workflow: {
        id: 'custom-path-test',
        name: 'Custom Path Test',
        version: '1.0.0',
        description: 'Test',
      },
      stack: {},
    };

    const context: GeneratorContext = {
      workflow: testWorkflow,
      extendedWorkflow: {
        documentation: {
          intents: [
            { type: 'setup_guide', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false,
              outputPath: 'getting-started.md',
            },
          ],
        },
      },
      outputDirectory: testOutputDir,
      executionPlan: { workflow: testWorkflow, componentPlans: new Map() },
    };

    const result = await generator.generate(context);

    const customFile = result.files.find(f => f.path.includes('getting-started.md'));
    expect(customFile).toBeDefined();
  });

  it('should include all models in API reference', async () => {
    const generator = new MarkdownDocumentationGenerator();

    const testWorkflow = {
      workflow: {
        id: 'models-test',
        name: 'Models Test',
        version: '1.0.0',
        description: 'Test',
      },
      stack: {},
    };

    const context: GeneratorContext = {
      workflow: testWorkflow,
      extendedWorkflow: {
        models: {
          User: {
            fields: {
              name: { type: 'string', required: true, unique: false, system_field: false, exclude_from_forms: false },
            },
            timestamps: true,
      soft_delete: false,
          },
          Post: {
            fields: {
              title: { type: 'string', required: true, unique: false, system_field: false, exclude_from_forms: false },
              content: { type: 'text', required: true, unique: false, system_field: false, exclude_from_forms: false },
            },
            timestamps: true,
      soft_delete: false,
          },
          Comment: {
            fields: {
              text: { type: 'text', required: true, unique: false, system_field: false, exclude_from_forms: false },
            },
            timestamps: true,
      soft_delete: false,
          },
        },
        documentation: {
          intents: [
            { type: 'api_reference', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false },
          ],
        },
      },
      outputDirectory: testOutputDir,
      executionPlan: { workflow: testWorkflow, componentPlans: new Map() },
    };

    const result = await generator.generate(context);

    // Write files
    for (const file of result.files) {
      const dir = path.dirname(file.path);
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
      }
      fs.writeFileSync(file.path, file.content);
    }

    const apiRefPath = path.join(testOutputDir, 'docs', 'api_reference.md');
    const content = fs.readFileSync(apiRefPath, 'utf-8');

    expect(content).toContain('### User');
    expect(content).toContain('### Post');
    expect(content).toContain('### Comment');
  });

  it('should generate index with all documentation links', async () => {
    const generator = new MarkdownDocumentationGenerator();

    const testWorkflow = {
      workflow: {
        id: 'index-test',
        name: 'Index Test',
        version: '1.0.0',
        description: 'Test application',
      },
      stack: {},
    };

    const context: GeneratorContext = {
      workflow: testWorkflow,
      extendedWorkflow: {
        documentation: {
          intents: [
            { type: 'setup_guide', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false },
            { type: 'api_reference', audience: 'developer', overwrite: 'always', includeExamples: false, includeCommonIssues: false },
            { type: 'tutorial', audience: 'both', overwrite: 'always', includeExamples: false, includeCommonIssues: false },
          ],
        },
      },
      outputDirectory: testOutputDir,
      executionPlan: { workflow: testWorkflow, componentPlans: new Map() },
    };

    const result = await generator.generate(context);

    // Write files
    for (const file of result.files) {
      const dir = path.dirname(file.path);
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
      }
      fs.writeFileSync(file.path, file.content);
    }

    const indexPath = path.join(testOutputDir, 'docs', 'README.md');
    const content = fs.readFileSync(indexPath, 'utf-8');

    expect(content).toContain('Index Test - Documentation');
    expect(content).toContain('Setup Guide');
    expect(content).toContain('API Reference');
    expect(content).toContain('Tutorial');
  });
});
