/*
 * Runtime Web – Unified Serverless Framework for Full-Stack TypeScript Applications
 * Documentation: https://runtimeweb.com/docs/getting-started
 *
 * @template: ai-chat
 */

/**
 * Template Scaffolding Property Tests
 *
 * Property-based tests for AI Chat template scaffolding.
 */

import * as fc from 'fast-check';
import * as path from 'path';
import * as fs from 'fs';

/**
 * Required directories in the scaffolded template.
 */
const REQUIRED_DIRECTORIES = [
    'application',
    'application/src',
    'application/src/components',
    'application/src/handlers',
    'application/src/services',
    'application/src/types',
    'application/src/hooks',
    'application/src/backend-services',
    'application/src/ties',
    'application/src/styles',
    'application/public',
    'cdk',
    'cdk/bin',
    'cdk/lib',
];

/**
 * Required files in the scaffolded template.
 */
const REQUIRED_FILES = [
    'application/package.json',
    'application/tsconfig.json',
    'application/runtime.config.ts',
    'application/README.md',
    'application/src/App.tsx',
    'application/src/index.tsx',
    'application/src/routes.tsx',
    'application/src/types/index.ts',
    'application/src/services/index.ts',
    'application/src/hooks/index.ts',
    'application/src/components/index.ts',
    'application/src/backend-services/index.ts',
    'application/src/ties/index.ts',
    'application/src/handlers/chat.handlers.ts',
    'cdk/package.json.template',
    'cdk/cdk.json.template',
    'cdk/tsconfig.json.template',
    'cdk/bin/app.ts.template',
    'cdk/lib/config.ts.template',
    'cdk/lib/ai-chat-stack.ts.template',
    'cdk/lib/infra-stack.ts.template',
    'cdk/lib/runtime-stack.ts.template',
    'cdk/lib/web-stack.ts.template',
    'cdk/lib/awake-stack.ts.template',
];

describe('Template Scaffolding Properties', () => {
    const templateRoot = path.join(__dirname, '..');

    /**
     * Feature: ai-chat-template, Property 1: Template Scaffolding Produces Valid Directory Structure
     *
     * For any valid project name, when the CLI init command is invoked with
     * `--template ai-chat`, the scaffolded project SHALL contain all required
     * directories and files.
     *
     * **Validates: Requirements 1.4, 1.5, 1.6**
     */
    describe('Property 1: Template Scaffolding Produces Valid Directory Structure', () => {
        it('should contain all required directories', async () => {
            await fc.assert(
                fc.asyncProperty(fc.constant(null), async () => {
                    for (const dir of REQUIRED_DIRECTORIES) {
                        const dirPath = path.join(templateRoot, dir);
                        const exists = fs.existsSync(dirPath);
                        expect(exists).toBe(true);
                    }
                }),
                { numRuns: 100 }
            );
        });

        it('should contain all required files', async () => {
            await fc.assert(
                fc.asyncProperty(fc.constant(null), async () => {
                    for (const file of REQUIRED_FILES) {
                        const filePath = path.join(templateRoot, file);
                        const exists = fs.existsSync(filePath);
                        expect(exists).toBe(true);
                    }
                }),
                { numRuns: 100 }
            );
        });

        it('should have valid package.json structure', async () => {
            await fc.assert(
                fc.asyncProperty(fc.constant(null), async () => {
                    const packageJsonPath = path.join(templateRoot, 'application/package.json');
                    const content = fs.readFileSync(packageJsonPath, 'utf-8');
                    const packageJson = JSON.parse(content);

                    // Required fields
                    expect(packageJson.name).toBeDefined();
                    expect(packageJson.version).toBeDefined();
                    expect(packageJson.scripts).toBeDefined();
                    expect(packageJson.dependencies).toBeDefined();
                    expect(packageJson.devDependencies).toBeDefined();

                    // Required dependencies
                    expect(packageJson.dependencies['@worktif/runtime']).toBeDefined();
                    expect(packageJson.dependencies['react']).toBeDefined();
                    expect(packageJson.dependencies['react-dom']).toBeDefined();

                    // Required dev dependencies
                    expect(packageJson.devDependencies['typescript']).toBeDefined();
                    expect(packageJson.devDependencies['fast-check']).toBeDefined();
                }),
                { numRuns: 100 }
            );
        });

        it('should have valid tsconfig.json structure', async () => {
            await fc.assert(
                fc.asyncProperty(fc.constant(null), async () => {
                    const tsconfigPath = path.join(templateRoot, 'application/tsconfig.json');
                    const content = fs.readFileSync(tsconfigPath, 'utf-8');
                    const tsconfig = JSON.parse(content);

                    // Required compiler options
                    expect(tsconfig.compilerOptions).toBeDefined();
                    expect(tsconfig.compilerOptions.strict).toBe(true);
                    expect(tsconfig.compilerOptions.jsx).toBeDefined();
                }),
                { numRuns: 100 }
            );
        });
    });

    /**
     * Feature: ai-chat-template, Property 20: Template Code Quality
     *
     * For any scaffolded AI Chat template, the source files SHALL NOT contain
     * TODO comments in the main flow, and the TypeScript code SHALL compile
     * without errors.
     *
     * **Validates: Requirements 14.1, 14.2, 14.4**
     */
    describe('Property 20: Template Code Quality', () => {
        it('should not contain TODO comments in main source files', async () => {
            const sourceFiles = [
                'application/src/App.tsx',
                'application/src/index.tsx',
                'application/src/routes.tsx',
                'application/src/handlers/chat.handlers.ts',
                'application/src/services/chat-api.service.ts',
                'application/src/services/session-manager.service.ts',
                'application/src/backend-services/bedrock.service.ts',
                'application/src/backend-services/memory.service.ts',
            ];

            await fc.assert(
                fc.asyncProperty(fc.constant(null), async () => {
                    for (const file of sourceFiles) {
                        const filePath = path.join(templateRoot, file);
                        if (fs.existsSync(filePath)) {
                            const content = fs.readFileSync(filePath, 'utf-8');
                            // Allow TODO in comments about optional features, but not in main flow
                            const todoMatches = content.match(/\/\/\s*TODO(?!:?\s*optional)/gi);
                            expect(todoMatches).toBeNull();
                        }
                    }
                }),
                { numRuns: 100 }
            );
        });

        it('should have consistent file structure across components', async () => {
            await fc.assert(
                fc.asyncProperty(fc.constant(null), async () => {
                    const componentDir = path.join(templateRoot, 'application/src/components/chat');
                    const indexPath = path.join(componentDir, 'index.ts');

                    // Index file should exist
                    expect(fs.existsSync(indexPath)).toBe(true);

                    // Index should export components
                    const indexContent = fs.readFileSync(indexPath, 'utf-8');
                    expect(indexContent).toContain('export');
                    expect(indexContent).toContain('ChatPage');
                    expect(indexContent).toContain('MessageList');
                    expect(indexContent).toContain('InputArea');
                }),
                { numRuns: 100 }
            );
        });

        it('should have Elastic License headers in all source files', async () => {
            const sourceFiles = [
                'application/src/App.tsx',
                'application/src/handlers/chat.handlers.ts',
                'application/src/services/chat-api.service.ts',
            ];

            await fc.assert(
                fc.asyncProperty(fc.constant(null), async () => {
                    for (const file of sourceFiles) {
                        const filePath = path.join(templateRoot, file);
                        if (fs.existsSync(filePath)) {
                            const content = fs.readFileSync(filePath, 'utf-8');
                            expect(content).toContain('Elastic License 2.0');
                        }
                    }
                }),
                { numRuns: 100 }
            );
        });
    });
});
