/**
 * Vigthoria Agent File Operations
 * 
 * Enables the AI agent to directly create, edit, delete, and rename files
 * in the user's workspace. Like Cursor Composer / Windsurf Cascade.
 * 
 * - Parses AI responses for file operation commands
 * - Creates files with proper directory structure
 * - Edits files with search/replace or full replacement (via diff provider)
 * - Terminal command execution
 * - Project scaffolding
 */

const vscode = require('vscode');
const path = require('path');

class VigthoriAgentFileOps {
    constructor(diffProvider) {
        this.diffProvider = diffProvider;
        this.operationHistory = [];
        this.maxHistory = 100;
        
        console.log('[AGENT-FILE-OPS] ✨ Initialized');
    }

    register(context) {
        context.subscriptions.push(
            vscode.commands.registerCommand('vigthoria.agentCreateFile', 
                (filePath, content) => this.createFile(filePath, content)),
            vscode.commands.registerCommand('vigthoria.agentEditFile', 
                (filePath, edits) => this.editFile(filePath, edits)),
            vscode.commands.registerCommand('vigthoria.agentDeleteFile', 
                (filePath) => this.deleteFile(filePath)),
            vscode.commands.registerCommand('vigthoria.agentUndoLast', 
                () => this.undoLastOperation()),
        );

        console.log('[AGENT-FILE-OPS] ✅ Registered');
    }

    /**
     * Parse an AI response and extract file operations
     * 
     * Supports formats:
     * ```create:path/to/file.js
     * content here
     * ```
     * 
     * ```edit:path/to/file.js
     * <<<< SEARCH
     * old code
     * ====
     * new code
     * >>>> REPLACE
     * ```
     * 
     * ```delete:path/to/file.js```
     * 
     * ```terminal
     * command here
     * ```
     */
    parseAIResponse(responseText) {
        const operations = [];
        
        // Pattern 1: ```create:filepath\ncontent\n```
        const createPattern = /```create:([^\n]+)\n([\s\S]*?)```/g;
        let match;
        while ((match = createPattern.exec(responseText)) !== null) {
            operations.push({
                type: 'create',
                filePath: match[1].trim(),
                content: match[2]
            });
        }

        // Pattern 2: ```edit:filepath\n<<<< SEARCH\nold\n====\nnew\n>>>> REPLACE\n```
        const editPattern = /```edit:([^\n]+)\n([\s\S]*?)```/g;
        while ((match = editPattern.exec(responseText)) !== null) {
            const filePath = match[1].trim();
            const body = match[2];
            
            // Parse SEARCH/REPLACE blocks
            const srPattern = /<<<< SEARCH\n([\s\S]*?)\n====\n([\s\S]*?)\n>>>> REPLACE/g;
            let srMatch;
            const edits = [];
            while ((srMatch = srPattern.exec(body)) !== null) {
                edits.push({
                    search: srMatch[1],
                    replace: srMatch[2]
                });
            }
            
            if (edits.length > 0) {
                operations.push({
                    type: 'edit',
                    filePath,
                    edits
                });
            } else {
                // Full file replacement
                operations.push({
                    type: 'edit',
                    filePath,
                    content: body
                });
            }
        }

        // Pattern 3: ```delete:filepath```
        const deletePattern = /```delete:([^\n`]+)```/g;
        while ((match = deletePattern.exec(responseText)) !== null) {
            operations.push({
                type: 'delete',
                filePath: match[1].trim()
            });
        }

        // Pattern 4: ```terminal\ncommand\n```  or ```bash\ncommand\n```
        const terminalPattern = /```(?:terminal|bash|shell|sh)\n([\s\S]*?)```/g;
        while ((match = terminalPattern.exec(responseText)) !== null) {
            operations.push({
                type: 'terminal',
                command: match[1].trim()
            });
        }

        return operations;
    }

    /**
     * Execute parsed operations
     */
    async executeOperations(operations) {
        const results = [];
        
        for (const op of operations) {
            try {
                let result;
                switch (op.type) {
                    case 'create':
                        result = await this.createFile(op.filePath, op.content);
                        break;
                    case 'edit':
                        result = await this.editFile(op.filePath, op.edits || op.content);
                        break;
                    case 'delete':
                        result = await this.deleteFile(op.filePath);
                        break;
                    case 'terminal':
                        result = await this.executeTerminalCommand(op.command);
                        break;
                }
                results.push({ ...op, success: true, result });
            } catch (error) {
                results.push({ ...op, success: false, error: error.message });
            }
        }

        return results;
    }

    /**
     * Create a new file in the workspace
     */
    async createFile(filePath, content) {
        const absolutePath = this._resolveWorkspacePath(filePath);
        if (!absolutePath) {
            throw new Error('No workspace folder open');
        }

        const uri = vscode.Uri.file(absolutePath);
        
        // Create directory structure
        const dir = path.dirname(absolutePath);
        await vscode.workspace.fs.createDirectory(vscode.Uri.file(dir));
        
        // Check if file exists
        let exists = false;
        try {
            await vscode.workspace.fs.stat(uri);
            exists = true;
        } catch (e) {
            // File doesn't exist — good
        }

        if (exists) {
            const overwrite = await vscode.window.showWarningMessage(
                `File ${path.basename(filePath)} already exists. Overwrite?`,
                'Overwrite', 'Cancel'
            );
            if (overwrite !== 'Overwrite') {
                return { action: 'skipped', filePath };
            }
        }

        // Write the file
        const data = Buffer.from(content || '', 'utf-8');
        await vscode.workspace.fs.writeFile(uri, data);

        // Record in history
        this._recordOperation({
            type: 'create',
            filePath: absolutePath,
            content,
            timestamp: Date.now()
        });

        // Open the file in editor
        const doc = await vscode.workspace.openTextDocument(uri);
        await vscode.window.showTextDocument(doc, { preview: false });

        return { action: 'created', filePath: absolutePath };
    }

    /**
     * Edit an existing file
     */
    async editFile(filePath, editsOrContent) {
        const absolutePath = this._resolveWorkspacePath(filePath);
        if (!absolutePath) throw new Error('No workspace folder open');

        const uri = vscode.Uri.file(absolutePath);
        
        // Read current content
        let currentContent;
        try {
            const data = await vscode.workspace.fs.readFile(uri);
            currentContent = Buffer.from(data).toString('utf-8');
        } catch (e) {
            throw new Error(`File not found: ${filePath}`);
        }

        let newContent;

        if (Array.isArray(editsOrContent)) {
            // Apply search/replace edits sequentially
            newContent = currentContent;
            for (const edit of editsOrContent) {
                if (edit.search && edit.replace !== undefined) {
                    if (newContent.includes(edit.search)) {
                        newContent = newContent.replace(edit.search, edit.replace);
                    } else {
                        console.warn(`[AGENT-FILE-OPS] Search text not found in ${filePath}`);
                    }
                }
            }
        } else if (typeof editsOrContent === 'string') {
            // Full file replacement
            newContent = editsOrContent;
        } else {
            throw new Error('Invalid edit format');
        }

        // Use diff provider to show changes inline
        if (this.diffProvider) {
            await this.diffProvider.proposeChanges({
                filePath: absolutePath,
                originalContent: currentContent,
                newContent,
                description: `AI edit: ${path.basename(filePath)}`
            });
        } else {
            // Direct apply if no diff provider
            const data = Buffer.from(newContent, 'utf-8');
            await vscode.workspace.fs.writeFile(uri, data);
        }

        this._recordOperation({
            type: 'edit',
            filePath: absolutePath,
            originalContent: currentContent,
            newContent,
            timestamp: Date.now()
        });

        return { action: 'edited', filePath: absolutePath };
    }

    /**
     * Delete a file from the workspace
     */
    async deleteFile(filePath) {
        const absolutePath = this._resolveWorkspacePath(filePath);
        if (!absolutePath) throw new Error('No workspace folder open');

        const uri = vscode.Uri.file(absolutePath);
        
        // Read content before deletion for undo
        let content = '';
        try {
            const data = await vscode.workspace.fs.readFile(uri);
            content = Buffer.from(data).toString('utf-8');
        } catch (e) {
            throw new Error(`File not found: ${filePath}`);
        }

        const confirm = await vscode.window.showWarningMessage(
            `Delete ${path.basename(filePath)}?`,
            { modal: true },
            'Delete'
        );
        
        if (confirm !== 'Delete') {
            return { action: 'skipped', filePath: absolutePath };
        }

        await vscode.workspace.fs.delete(uri);

        this._recordOperation({
            type: 'delete',
            filePath: absolutePath,
            content,
            timestamp: Date.now()
        });

        return { action: 'deleted', filePath: absolutePath };
    }

    /**
     * Execute a terminal command
     */
    async executeTerminalCommand(command) {
        const terminal = vscode.window.createTerminal({
            name: 'Vigthoria Agent',
            cwd: this._getWorkspaceRoot()
        });
        terminal.show();
        terminal.sendText(command);

        this._recordOperation({
            type: 'terminal',
            command,
            timestamp: Date.now()
        });

        return { action: 'executed', command };
    }

    /**
     * Undo the last file operation
     */
    async undoLastOperation() {
        const lastOp = this.operationHistory.pop();
        if (!lastOp) {
            vscode.window.showInformationMessage('Nothing to undo');
            return;
        }

        try {
            switch (lastOp.type) {
                case 'create': {
                    // Undo create = delete the file
                    const uri = vscode.Uri.file(lastOp.filePath);
                    await vscode.workspace.fs.delete(uri);
                    vscode.window.showInformationMessage(`Undone: removed ${path.basename(lastOp.filePath)}`);
                    break;
                }
                case 'edit': {
                    // Undo edit = restore original content
                    const uri = vscode.Uri.file(lastOp.filePath);
                    const data = Buffer.from(lastOp.originalContent, 'utf-8');
                    await vscode.workspace.fs.writeFile(uri, data);
                    vscode.window.showInformationMessage(`Undone: restored ${path.basename(lastOp.filePath)}`);
                    break;
                }
                case 'delete': {
                    // Undo delete = recreate the file
                    const uri = vscode.Uri.file(lastOp.filePath);
                    const dir = path.dirname(lastOp.filePath);
                    await vscode.workspace.fs.createDirectory(vscode.Uri.file(dir));
                    const data = Buffer.from(lastOp.content, 'utf-8');
                    await vscode.workspace.fs.writeFile(uri, data);
                    vscode.window.showInformationMessage(`Undone: restored ${path.basename(lastOp.filePath)}`);
                    break;
                }
            }
        } catch (error) {
            vscode.window.showErrorMessage(`Undo failed: ${error.message}`);
        }
    }

    /**
     * Resolve a relative path to an absolute workspace path
     */
    _resolveWorkspacePath(filePath) {
        if (path.isAbsolute(filePath)) return filePath;
        
        const root = this._getWorkspaceRoot();
        if (!root) return null;
        
        return path.join(root, filePath);
    }

    _getWorkspaceRoot() {
        const folders = vscode.workspace.workspaceFolders;
        return folders && folders.length > 0 ? folders[0].uri.fsPath : null;
    }

    _recordOperation(op) {
        this.operationHistory.push(op);
        if (this.operationHistory.length > this.maxHistory) {
            this.operationHistory.shift();
        }
    }

    dispose() {
        this.operationHistory = [];
    }
}

module.exports = { VigthoriAgentFileOps };
