"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateVariantCode = void 0;
const AgentCore_1 = require("./agent/AgentCore");
const WorktreeManager_1 = require("./WorktreeManager");
const logger_1 = require("../utils/logger");
const CommentVariationService_1 = require("./CommentVariationService");
const log = (0, logger_1.createLogger)('VariantCodeGeneratorService');
const buildAgentPrompt = (instruction, changeSpec, element, fileExcerpts) => {
    const filePath = element.filePaths?.[0]?.filePath ?? 'unknown';
    const componentTree = element.componentTree
        ? element.componentTree.map((n) => n.name).join(' > ')
        : '';
    const fileSection = fileExcerpts.length > 0
        ? `\nRelevant source files (use these directly — no need to re-read):\n${fileExcerpts
            .map((f) => `\`\`\`\n// ${f.path}\n${f.content}\n\`\`\``)
            .join('\n\n')}`
        : '';
    return `Implement this design direction in the codebase.

Original user instruction: ${instruction}

Design direction to implement: ${changeSpec}

Target element:
- File: ${filePath}
- XPath: ${element.xpath}
- Tag: <${element.tagName}>
- Component hierarchy: ${componentTree}
- Text content: ${element.textContent?.slice(0, 80) ?? '(none)'}
${fileSection}
${fileExcerpts.length > 0
        ? 'Implement exactly the design direction described above using the file contents above as your starting point.'
        : 'Read the relevant source files, then implement exactly the design direction described above.'} Focus only on this specific change. Make the minimal changes needed to achieve the direction. Do not make unrelated modifications.`;
};
const generateVariantCode = async ({ sessionId, projectPath, instruction, element, variants, currentAppliedDiff, onEvent, abortController, }) => {
    const manager = new WorktreeManager_1.WorktreeManager(projectPath);
    let worktreePaths = [];
    let reversedAppliedDiff = false;
    // Reverse any variant currently applied to the main tree so worktrees are
    // seeded against the user's clean state. Without this, new variants' diffs
    // would carry context lines from the applied-variant state and fail to
    // apply once that state is reverted (e.g. when the prior comment is
    // deleted). If reverse fails, bail — generating against a contaminated
    // baseline would produce diffs that can't apply cleanly later.
    if (currentAppliedDiff) {
        try {
            await manager.applyDiff(currentAppliedDiff, true);
            reversedAppliedDiff = true;
            log.info('Reversed currently-applied variant diff before worktree creation');
        }
        catch (e) {
            log.error('Failed to reverse currently-applied variant diff — aborting variant generation:', e);
            onEvent({ type: 'session_complete' });
            throw e;
        }
    }
    try {
        const fileExcerpts = await (0, CommentVariationService_1.readFileExcerpts)(projectPath, element);
        worktreePaths = await manager.createWorktrees(sessionId, variants.length);
        await Promise.all(variants.map(async (variant, i) => {
            const worktreePath = worktreePaths[i];
            onEvent({ type: 'variant_started', variantIndex: variant.index });
            try {
                const agentCore = new AgentCore_1.AgentCore();
                await agentCore.execute({
                    systemPrompt: fileExcerpts.length > 0
                        ? 'You are a frontend engineer implementing a specific design direction. The relevant source files are already provided in the prompt — use them directly without re-reading. Make the targeted code change described. Minimal, focused changes only.'
                        : 'You are a frontend engineer implementing a specific design direction. Read the relevant files, then make the targeted code change described. Minimal, focused changes only.',
                    userPrompt: buildAgentPrompt(instruction, variant.changeSpec, element, fileExcerpts),
                    allowedTools: ['Read', 'Glob', 'Grep', 'Edit', 'Write'],
                    permissionMode: 'bypassPermissions',
                    cwd: worktreePath,
                    abortController,
                    onProgress: () => { },
                    executionPolicy: { disableSubagents: true },
                });
                const diff = await manager.getDiff(worktreePath);
                onEvent({ type: 'variant_completed', variantIndex: variant.index, diff });
            }
            catch (e) {
                const error = e instanceof Error ? e.message : 'Code generation failed';
                log.error(`Variant ${variant.index} failed:`, error);
                onEvent({ type: 'variant_error', variantIndex: variant.index, error });
            }
        }));
    }
    finally {
        // Re-apply the previously-applied diff so the iframe restores to the
        // state the user was seeing before generation. A failure here leaves
        // the main tree clean — the user will see the variant overlay drop —
        // but variants are already generated, so we just log and move on.
        if (reversedAppliedDiff && currentAppliedDiff) {
            try {
                await manager.applyDiff(currentAppliedDiff, false);
                log.info('Re-applied previously-applied variant diff after generation');
            }
            catch (e) {
                log.warn('Failed to re-apply previously-applied variant diff after generation:', e);
            }
        }
        onEvent({ type: 'session_complete' });
        await manager
            .cleanupSession(sessionId)
            .catch((e) => log.warn('Cleanup failed:', e));
    }
};
exports.generateVariantCode = generateVariantCode;
//# sourceMappingURL=VariantCodeGeneratorService.js.map