import * as fs from 'fs';
import * as path from 'path';
import { validatePath } from '../../security';
import { FileSystemError } from '../../core/errors';
import { HandlerContext } from './types';

/**
 * `<create_file>` + `<edit_file>` action handler.
 *
 * AI 가 한 턴에 여러 개의 create/edit 태그를 내뱉을 수 있으므로, 각 태그마다
 * regex 로 잡아서 순서대로 처리한다. validatePath() 로 sandbox 보장 + 매 파일
 * 쓰기 전에 transactionManager.record() 로 롤백 지점 기록.
 */
export async function applyFileCreateEditActions(ctx: HandlerContext): Promise<void> {
    const { aiMessage, rootPath, activeBrainDir, report } = ctx;

    // Action 1: Create File
    const createRegex = /<create_file\s+path=['"]?([^'"]+)['"]?>([\s\S]*?)<\/create_file>/gi;
    let match;
    while ((match = createRegex.exec(aiMessage)) !== null) {
        const relPath = match[1].trim();
        const content = match[2].trim();
        try {
            const absPath = validatePath(rootPath, relPath);
            await ctx.transactionManager.record(absPath);

            fs.mkdirSync(path.dirname(absPath), { recursive: true });
            fs.writeFileSync(absPath, content, 'utf-8');

            report.push(`✅ Created: ${relPath}`);
            ctx.setFirstCreated(absPath);
            if (absPath.startsWith(activeBrainDir)) ctx.markBrainModified();
        } catch (err: any) {
            throw new FileSystemError(`Failed to create file ${relPath}: ${err.message}`, relPath, err);
        }
    }

    // Action 2: Edit File
    const editRegex = /<edit_file\s+path=['"]?([^'"]+)['"]?>([\s\S]*?)<\/edit_file>/gi;
    while ((match = editRegex.exec(aiMessage)) !== null) {
        const relPath = match[1].trim();
        const editContent = match[2].trim();
        try {
            const absPath = validatePath(rootPath, relPath);
            if (fs.existsSync(absPath)) {
                await ctx.transactionManager.record(absPath);

                let currentContent = fs.readFileSync(absPath, 'utf-8');
                const searchMatch = editContent.match(/<search>([\s\S]*?)<\/search>\s*<replace>([\s\S]*?)<\/replace>/i);

                if (searchMatch) {
                    const searchStr = searchMatch[1];
                    const replaceStr = searchMatch[2];
                    if (currentContent.includes(searchStr)) {
                        currentContent = currentContent.replace(searchStr, replaceStr);
                        fs.writeFileSync(absPath, currentContent, 'utf-8');
                        report.push(`📝 Updated: ${relPath}`);
                    } else {
                        report.push(`⚠️ Search string not found in ${relPath}`);
                    }
                } else {
                    fs.writeFileSync(absPath, editContent, 'utf-8');
                    report.push(`📝 Updated (Full): ${relPath}`);
                }
                if (absPath.startsWith(activeBrainDir)) ctx.markBrainModified();
            } else {
                report.push(`❌ File not found: ${relPath}`);
            }
        } catch (err: any) {
            throw new FileSystemError(`Failed to edit file ${relPath}: ${err.message}`, relPath, err);
        }
    }
}
