import { z } from 'zod';
import { createModuleLogger } from '../logger.js';
import { safePathSchema } from './validators.js';
import { Xcode } from '../utils/projects/Xcode.js';
import { SwiftPackage } from '../utils/projects/SwiftPackage.js';
import { XcodeError, XcodeErrorType } from '../utils/projects/XcodeErrors.js';
import { formatCompileErrors } from '../utils/errorFormatting.js';
import { formatBuildErrors } from '../utils/buildErrorParsing.js';
import path from 'path';
const logger = createModuleLogger('TestSwiftPackageTool');
export const testSwiftPackageSchema = z.object({
    packagePath: safePathSchema,
    filter: z.string().optional(),
    configuration: z.enum(['Debug', 'Release']).default('Debug')
});
/**
 * Test Swift Package Tool - runs tests for Swift packages
 */
export class TestSwiftPackageTool {
    xcode;
    constructor(xcode) {
        this.xcode = xcode || new Xcode();
    }
    getToolDefinition() {
        return {
            name: 'test_swift_package',
            description: 'Run tests for a Swift Package Manager package',
            inputSchema: {
                type: 'object',
                properties: {
                    packagePath: {
                        type: 'string',
                        description: 'Path to Package.swift or package directory'
                    },
                    filter: {
                        type: 'string',
                        description: 'Filter for specific tests (e.g., "MyPackageTests.UserTests" for a class, "MyPackageTests.UserTests/testLogin" for a method)'
                    },
                    configuration: {
                        type: 'string',
                        description: 'Build configuration (Debug or Release)',
                        enum: ['Debug', 'Release'],
                        default: 'Debug'
                    }
                },
                required: ['packagePath']
            }
        };
    }
    async execute(args) {
        const validated = testSwiftPackageSchema.parse(args);
        const { packagePath, filter, configuration } = validated;
        logger.info({ packagePath, filter, configuration }, 'Running Swift package tests');
        try {
            // Open the package using Xcode utility
            const project = await this.xcode.open(packagePath);
            // Ensure it's a Swift package, not an Xcode project
            if (!(project instanceof SwiftPackage)) {
                throw new Error(`No Package.swift found at: ${packagePath}`);
            }
            // Run tests using SwiftPackage
            const testResult = await project.test({
                filter,
                configuration
            });
            // Check for compile errors first
            if (testResult.compileErrors && testResult.compileErrors.length > 0) {
                const { summary, errorList } = formatCompileErrors(testResult.compileErrors);
                return {
                    content: [
                        {
                            type: 'text',
                            text: `${summary}\n${errorList}\n\nPackage: ${path.basename(project.path)}\nConfiguration: ${configuration}\n\n📁 Full logs saved to: ${testResult.logPath}`
                        }
                    ]
                };
            }
            // Check for build errors
            if (testResult.buildErrors && testResult.buildErrors.length > 0) {
                const errorText = formatBuildErrors(testResult.buildErrors);
                return {
                    content: [
                        {
                            type: 'text',
                            text: `${errorText}\n\nPackage: ${path.basename(project.path)}\nConfiguration: ${configuration}\n\n📁 Full logs saved to: ${testResult.logPath}`
                        }
                    ]
                };
            }
            if (!testResult.success && testResult.failed === 0 && testResult.passed === 0) {
                // Other non-test failures (configuration errors, etc) - extract error message from output
                const output = testResult.output || '';
                let errorMessage = '❌ Test execution failed';
                // Try to extract the actual error message
                if (output.includes('error:')) {
                    const errorMatch = output.match(/error:\s*(.+?)(?:\n|$)/);
                    if (errorMatch) {
                        errorMessage = `❌ Test execution failed: ${errorMatch[1]}`;
                    }
                }
                return {
                    content: [
                        {
                            type: 'text',
                            text: `${errorMessage}\n\nPackage: ${path.basename(project.path)}\nConfiguration: ${configuration}\n\n📁 Full logs saved to: ${testResult.logPath}`
                        }
                    ]
                };
            }
            // Format the results
            const icon = testResult.success ? '✅' : '❌';
            const summary = `${icon} Tests ${testResult.success ? 'passed' : 'failed'}: ${testResult.passed} passed, ${testResult.failed} failed`;
            const failingTestsList = testResult.failingTests && testResult.failingTests.length > 0
                ? `\n\n**Failing tests:**\n${testResult.failingTests.map(t => `• ${t.identifier}\n  ${t.reason}`).join('\n\n')}`
                : '';
            return {
                content: [
                    {
                        type: 'text',
                        text: `${summary}${failingTestsList}\n\nPackage: ${path.basename(project.path)}\nConfiguration: ${configuration}\n${filter ? `Filter: ${filter}\n` : ''}\n📁 Full logs saved to: ${testResult.logPath}`
                    }
                ]
            };
        }
        catch (error) {
            logger.error({ error, packagePath }, 'Swift package tests failed');
            // Handle XcodeError with context-specific message
            let displayMessage = '❌ ';
            if (error instanceof XcodeError && error.type === XcodeErrorType.ProjectNotFound) {
                displayMessage += `No Package.swift found at: ${error.path}`;
            }
            else {
                const errorMessage = error.message || 'Unknown test error';
                displayMessage += `Test execution failed: ${errorMessage.split('\n')[0]}`;
            }
            return {
                content: [
                    {
                        type: 'text',
                        text: displayMessage
                    }
                ]
            };
        }
    }
}
//# sourceMappingURL=TestSwiftPackageTool.js.map