import { readFileSync, writeFileSync, existsSync } from 'fs';
import { join } from 'path';
import { createModuleLogger } from '../../logger';
const logger = createModuleLogger('TestErrorInjector');
/**
 * Helper class to inject specific error conditions into test projects
 * for testing error handling and display
 */
export class TestErrorInjector {
    originalFiles = new Map();
    /**
     * Inject a compile error into a Swift file
     */
    injectCompileError(filePath, errorType = 'type-mismatch') {
        this.backupFile(filePath);
        let content = readFileSync(filePath, 'utf8');
        switch (errorType) {
            case 'type-mismatch':
                // Add a type mismatch error
                content = content.replace('let newItem = Item(timestamp: Date())', 'let x: String = 123  // Type mismatch error\n        let newItem = Item(timestamp: Date())');
                break;
            case 'syntax':
                // Add a syntax error
                content = content.replace('import SwiftUI', 'import SwiftUI\nlet incomplete = // Syntax error');
                break;
            case 'missing-member':
                // Reference a non-existent property
                content = content.replace('modelContext.insert(newItem)', 'modelContext.insert(newItem)\n        let _ = newItem.nonExistentProperty // Missing member error');
                break;
        }
        writeFileSync(filePath, content);
        logger.debug({ filePath, errorType }, 'Injected compile error');
    }
    /**
     * Remove code signing from a project to trigger signing errors
     */
    injectCodeSigningError(projectPath) {
        const pbxprojPath = join(projectPath, 'project.pbxproj');
        if (!existsSync(pbxprojPath)) {
            throw new Error(`Project file not found: ${pbxprojPath}`);
        }
        this.backupFile(pbxprojPath);
        let content = readFileSync(pbxprojPath, 'utf8');
        // Change code signing settings to trigger errors
        content = content.replace(/CODE_SIGN_STYLE = Automatic;/g, 'CODE_SIGN_STYLE = Manual;');
        content = content.replace(/DEVELOPMENT_TEAM = [A-Z0-9]+;/g, 'DEVELOPMENT_TEAM = "";');
        writeFileSync(pbxprojPath, content);
        logger.debug({ projectPath }, 'Injected code signing error');
    }
    /**
     * Inject a provisioning profile error by requiring a non-existent profile
     */
    injectProvisioningError(projectPath) {
        const pbxprojPath = join(projectPath, 'project.pbxproj');
        if (!existsSync(pbxprojPath)) {
            throw new Error(`Project file not found: ${pbxprojPath}`);
        }
        this.backupFile(pbxprojPath);
        let content = readFileSync(pbxprojPath, 'utf8');
        // Add a non-existent provisioning profile requirement
        content = content.replace(/PRODUCT_BUNDLE_IDENTIFIER = /g, 'PROVISIONING_PROFILE_SPECIFIER = "NonExistent Profile";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = ');
        writeFileSync(pbxprojPath, content);
        logger.debug({ projectPath }, 'Injected provisioning profile error');
    }
    /**
     * Inject a missing dependency error into a Swift package
     */
    injectMissingDependency(packagePath) {
        const packageSwiftPath = join(packagePath, 'Package.swift');
        if (!existsSync(packageSwiftPath)) {
            throw new Error(`Package.swift not found: ${packageSwiftPath}`);
        }
        this.backupFile(packageSwiftPath);
        let content = readFileSync(packageSwiftPath, 'utf8');
        // Add a non-existent package dependency
        const dependenciesMatch = content.match(/dependencies:\s*\[([^\]]*)\]/);
        if (dependenciesMatch) {
            const newDependency = '.package(url: "https://github.com/nonexistent/package.git", from: "1.0.0"),';
            content = content.replace(dependenciesMatch[0], `dependencies: [\n        ${newDependency}\n${dependenciesMatch[1]}]`);
        }
        // Also add import to a source file to trigger the error
        const sourcePath = join(packagePath, 'Sources');
        if (existsSync(sourcePath)) {
            const sourceFiles = require('fs').readdirSync(sourcePath, { recursive: true })
                .filter((f) => f.endsWith('.swift'));
            if (sourceFiles.length > 0) {
                const sourceFile = join(sourcePath, sourceFiles[0]);
                this.backupFile(sourceFile);
                let sourceContent = readFileSync(sourceFile, 'utf8');
                sourceContent = 'import NonExistentPackage\n' + sourceContent;
                writeFileSync(sourceFile, sourceContent);
            }
        }
        writeFileSync(packageSwiftPath, content);
        logger.debug({ packagePath }, 'Injected missing dependency error');
    }
    /**
     * Inject a platform compatibility error
     */
    injectPlatformError(projectPath) {
        const pbxprojPath = join(projectPath, 'project.pbxproj');
        if (!existsSync(pbxprojPath)) {
            throw new Error(`Project file not found: ${pbxprojPath}`);
        }
        this.backupFile(pbxprojPath);
        let content = readFileSync(pbxprojPath, 'utf8');
        // Set incompatible deployment targets
        content = content.replace(/IPHONEOS_DEPLOYMENT_TARGET = \d+\.\d+;/g, 'IPHONEOS_DEPLOYMENT_TARGET = 99.0;' // Impossible iOS version
        );
        writeFileSync(pbxprojPath, content);
        logger.debug({ projectPath }, 'Injected platform compatibility error');
    }
    /**
     * Backup a file before modifying it
     */
    backupFile(filePath) {
        if (!this.originalFiles.has(filePath)) {
            const content = readFileSync(filePath, 'utf8');
            this.originalFiles.set(filePath, content);
            logger.debug({ filePath }, 'Backed up original file');
        }
    }
    /**
     * Restore all modified files to their original state
     */
    restoreAll() {
        for (const [filePath, content] of this.originalFiles) {
            writeFileSync(filePath, content);
            logger.debug({ filePath }, 'Restored original file');
        }
        this.originalFiles.clear();
    }
    /**
     * Restore a specific file
     */
    restoreFile(filePath) {
        const original = this.originalFiles.get(filePath);
        if (original) {
            writeFileSync(filePath, original);
            this.originalFiles.delete(filePath);
            logger.debug({ filePath }, 'Restored original file');
        }
    }
}
//# sourceMappingURL=TestErrorInjector.js.map