import * as path from 'path';
export class PlaywrightGenerator {
    constructor(options = {}) {
        this.validateOptions(options);
        this.options = { ...PlaywrightGenerator.DEFAULT_OPTIONS, ...options };
    }
    validateOptions(options) {
        if (options.outputPath && typeof options.outputPath !== 'string') {
            throw new Error('outputPath must be a string');
        }
        if (options.testNamePrefix && typeof options.testNamePrefix !== 'string') {
            throw new Error('testNamePrefix must be a string');
        }
        if (options.includeComments !== undefined && typeof options.includeComments !== 'boolean') {
            throw new Error('includeComments must be a boolean');
        }
    }
    async generateTest(session) {
        if (!session || !Array.isArray(session.actions)) {
            throw new Error('Invalid session data');
        }
        const testCase = this.createTestCase(session);
        const testCode = this.generateTestCode(testCase);
        const filePath = this.getOutputFilePath(session);
        return {
            testCode,
            filePath,
            sessionId: session.id,
        };
    }
    createTestCase(session) {
        const testCase = {
            name: `${this.options.testNamePrefix}_${new Date(session.startTime).toISOString().split('T')[0]}`,
            steps: [],
            imports: new Set(['test', 'expect']),
        };
        for (const action of session.actions) {
            const step = this.convertActionToStep(action);
            if (step) {
                testCase.steps.push(step);
            }
        }
        return testCase;
    }
    convertActionToStep(action) {
        const { toolName, parameters } = action;
        switch (toolName) {
            case 'playwright_navigate':
                return this.generateNavigateStep(parameters);
            case 'playwright_fill':
                return this.generateFillStep(parameters);
            case 'playwright_click':
                return this.generateClickStep(parameters);
            case 'playwright_screenshot':
                return this.generateScreenshotStep(parameters);
            case 'playwright_expect_response':
                return this.generateExpectResponseStep(parameters);
            case 'playwright_assert_response':
                return this.generateAssertResponseStep(parameters);
            case 'playwright_hover':
                return this.generateHoverStep(parameters);
            case 'playwright_select':
                return this.generateSelectStep(parameters);
            case 'playwright_custom_user_agent':
                return this.generateCustomUserAgentStep(parameters);
            default:
                console.warn(`Unsupported tool: ${toolName}`);
                return null;
        }
    }
    generateNavigateStep(parameters) {
        const { url, waitUntil } = parameters;
        const options = waitUntil ? `, { waitUntil: '${waitUntil}' }` : '';
        return `
    // Navigate to URL
    await page.goto('${url}'${options});`;
    }
    generateFillStep(parameters) {
        const { selector, value } = parameters;
        return `
    // Fill input field
    await page.fill('${selector}', '${value}');`;
    }
    generateClickStep(parameters) {
        const { selector } = parameters;
        return `
    // Click element
    await page.click('${selector}');`;
    }
    generateScreenshotStep(parameters) {
        const { name, fullPage = false, path } = parameters;
        const options = [];
        if (fullPage)
            options.push('fullPage: true');
        if (path)
            options.push(`path: '${path}'`);
        const optionsStr = options.length > 0 ? `, { ${options.join(', ')} }` : '';
        return `
    // Take screenshot
    await page.screenshot({ path: '${name}.png'${optionsStr} });`;
    }
    generateExpectResponseStep(parameters) {
        const { url, id } = parameters;
        return `
    // Wait for response
    const ${id}Response = page.waitForResponse('${url}');`;
    }
    generateAssertResponseStep(parameters) {
        const { id, value } = parameters;
        const assertion = value
            ? `\n    const responseText = await ${id}Response.text();\n    expect(responseText).toContain('${value}');`
            : `\n    expect(${id}Response.ok()).toBeTruthy();`;
        return `
    // Assert response${assertion}`;
    }
    generateHoverStep(parameters) {
        const { selector } = parameters;
        return `
    // Hover over element
    await page.hover('${selector}');`;
    }
    generateSelectStep(parameters) {
        const { selector, value } = parameters;
        return `
    // Select option
    await page.selectOption('${selector}', '${value}');`;
    }
    generateCustomUserAgentStep(parameters) {
        const { userAgent } = parameters;
        return `
    // Set custom user agent
    await context.setUserAgent('${userAgent}');`;
    }
    generateTestCode(testCase) {
        const imports = Array.from(testCase.imports)
            .map(imp => `import { ${imp} } from '@playwright/test';`)
            .join('\n');
        return `
${imports}

test('${testCase.name}', async ({ page, context }) => {
  ${testCase.steps.join('\n')}
});`;
    }
    getOutputFilePath(session) {
        if (!session.id) {
            throw new Error('Session ID is required');
        }
        const sanitizedPrefix = this.options.testNamePrefix.toLowerCase().replace(/[^a-z0-9_]/g, '_');
        const fileName = `${sanitizedPrefix}_${session.id}.spec.ts`;
        return path.resolve(this.options.outputPath, fileName);
    }
}
PlaywrightGenerator.DEFAULT_OPTIONS = {
    outputPath: 'tests',
    testNamePrefix: 'MCP',
    includeComments: true,
};
