/**
 * Vigthoria Chat Participant - VS Code Chat API Integration
 * 
 * Uses the modern VS Code Chat Participant API for native streaming responses.
 * Supports @vigthoria mentions with /build, /agent, /operator commands.
 * 
 * Key Features:
 * - stream.markdown() for real-time token streaming
 * - stream.progress() for status updates
 * - stream.reference() for file context display
 * - Native VS Code Chat UI integration
 */

const vscode = require('vscode');
const { CONFIG } = require('../utils/config');

class VigthoriaChatParticipant {
    constructor() {
        this.aiService = null;
        this.authService = null;
        this.conversationHistory = [];
        this.MODEL_ROUTER_URL = (CONFIG && CONFIG.server && CONFIG.server.modelRouterUrl ? CONFIG.server.modelRouterUrl : 'https://coder.vigthoria.io/api/model-router') + '/route';
        this.PARTICIPANT_ID = 'vigthoria-ai-chat.vigthoria';
    }

    /**
     * Set the AI service for processing requests
     */
    setAIService(aiService) {
        this.aiService = aiService;
    }

    /**
     * Set the auth service for subscription verification
     */
    setAuthService(authService) {
        this.authService = authService;
        console.log('🔐 Chat Participant connected to Auth Service');
    }

    /**
     * Register the chat participant with VS Code
     * @param {vscode.ExtensionContext} context 
     */
    register(context) {
        console.log('🤖 Registering Vigthoria Chat Participant...');
        
        const participant = vscode.chat.createChatParticipant(
            this.PARTICIPANT_ID,
            this.handleChatRequest.bind(this)
        );

        // Set participant metadata
        participant.iconPath = vscode.Uri.joinPath(context.extensionUri, 'vigthoria-icon.png');
        
        // Handle follow-up questions
        participant.followupProvider = {
            provideFollowups: (result, context, token) => {
                return this.provideFollowups(result, context);
            }
        };

        context.subscriptions.push(participant);
        console.log('✅ Vigthoria Chat Participant registered successfully');
        
        return participant;
    }

    /**
     * Main chat request handler - called when user @mentions vigthoria
     * @param {vscode.ChatRequest} request 
     * @param {vscode.ChatContext} context 
     * @param {vscode.ChatResponseStream} stream 
     * @param {vscode.CancellationToken} token 
     */
    async handleChatRequest(request, context, stream, token) {
        const startTime = Date.now();
        
        try {
            // Determine the mode from command or default to 'build'
            const mode = this.getModeFromCommand(request.command);
            const userMessage = request.prompt;
            
            console.log(`🎯 [Vigthoria Chat] Mode: ${mode}, Message: "${userMessage.substring(0, 50)}..."`);

            // 🔐 SUBSCRIPTION CHECK - Verify user has access to this mode
            if (this.authService) {
                const canUse = this.authService.canUseMode(mode);
                if (!canUse) {
                    const subInfo = this.authService.getSubscriptionInfo();
                    stream.markdown(`\n\n🔒 **${mode.toUpperCase()} Mode requires ${this.getRequiredTierForMode(mode)} subscription**\n\n`);
                    stream.markdown(`Your current plan: **${subInfo.tierName}**\n\n`);
                    stream.markdown(`Available modes: ${subInfo.limits?.modes?.join(', ') || 'ask'}\n\n`);
                    stream.markdown(`[Upgrade your plan](https://coder.vigthoria.io/pricing) to access ${mode} mode.`);
                    return { metadata: { error: 'subscription_required', mode: mode } };
                }
                
                // Check daily request limit
                if (!this.authService.checkRateLimit()) {
                    const limits = this.authService.getSubscriptionInfo().limits;
                    stream.markdown(`\n\n⚠️ **Daily request limit reached**\n\n`);
                    stream.markdown(`Your plan allows ${limits.dailyRequests} requests per day.\n\n`);
                    stream.markdown(`[Upgrade your plan](https://coder.vigthoria.io/pricing) for more requests.`);
                    return { metadata: { error: 'rate_limit', mode: mode } };
                }
            }

            // Show progress indicator
            stream.progress(`🤖 Vigthoria ${mode.toUpperCase()} mode activated...`);

            // Handle V3 integrated commands that talk to the backend directly
            const v3Modes = ['history', 'replay', 'fork', 'deploy', 'legion', 'seal'];
            if (v3Modes.includes(mode)) {
                return await this.handleV3Command(mode, userMessage, stream, token);
            }

            // Get file context from references
            const fileContext = await this.extractFileContext(request, stream);
            
            // Build the prompt with context
            const enhancedPrompt = this.buildEnhancedPrompt(userMessage, mode, fileContext, context.history);
            
            // Stream the AI response
            await this.streamAIResponse(enhancedPrompt, mode, stream, token);
            
            const duration = Date.now() - startTime;
            console.log(`✅ [Vigthoria Chat] Response completed in ${duration}ms`);
            
            // Return metadata for follow-ups
            return {
                metadata: {
                    mode: mode,
                    duration: duration,
                    filesAnalyzed: fileContext.files?.length || 0
                }
            };
            
        } catch (error) {
            console.error('❌ [Vigthoria Chat] Error:', error);
            stream.markdown(`\n\n❌ **Error:** ${error.message}\n\nPlease try again or check if the AI service is running.`);
            return { metadata: { error: error.message } };
        }
    }

    /**
     * Determine mode from slash command
     */
    getModeFromCommand(command) {
        const commandModes = {
            'build': 'build',
            'agent': 'agent',
            'operator': 'operator',
            'analyze': 'build',
            'explain': 'ask',
            'history': 'history',
            'replay': 'replay',
            'fork': 'fork',
            'deploy': 'deploy',
            'legion': 'legion',
            'seal': 'seal'
        };
        return commandModes[command] || 'build';
    }

    /**
     * Get required subscription tier for a mode
     */
    getRequiredTierForMode(mode) {
        const tierRequirements = {
            'ask': 'Developer',
            'build': 'Developer',
            'agent': 'Pro',
            'operator': 'Enterprise'
        };
        return tierRequirements[mode] || 'Developer';
    }

    /**
     * Handle V3 integrated slash commands (history, replay, fork, deploy, legion, seal)
     */
    async handleV3Command(mode, userMessage, stream, token) {
        const { AIService } = require('../services/ai-service');
        const ai = new AIService();

        try {
            switch (mode) {
                case 'history': {
                    stream.progress('📜 Fetching run history...');
                    const runs = await ai.fetchRunHistory(10);
                    if (!runs || !runs.runs || runs.runs.length === 0) {
                        stream.markdown('No agent runs found yet. Run an `/agent` task first.\n');
                    } else {
                        stream.markdown('## 📜 Recent Agent Runs\n\n');
                        stream.markdown('| # | Run ID | Request | Status | Date |\n|---|--------|---------|--------|------|\n');
                        for (const [i, run] of runs.runs.entries()) {
                            const req = (run.request || '').substring(0, 50);
                            const date = run.timestamp ? new Date(run.timestamp * 1000).toLocaleString() : '—';
                            stream.markdown(`| ${i + 1} | \`${run.run_id}\` | ${req} | ${run.status || '—'} | ${date} |\n`);
                        }
                        stream.markdown('\nUse `/replay <run-id>` to replay or `/fork <run-id>` to fork.\n');
                    }
                    break;
                }
                case 'replay': {
                    const runId = userMessage.trim();
                    if (!runId) {
                        stream.markdown('Usage: `/replay <run-id>`\nGet run IDs from `/history`.\n');
                        break;
                    }
                    stream.progress(`🔄 Fetching events for ${runId}...`);
                    const events = await ai.fetchRunEvents(runId);
                    stream.markdown(`## 🔄 Replay: \`${runId}\`\n\n`);
                    if (events && events.events) {
                        for (const evt of events.events) {
                            if (evt.type === 'tool_call') {
                                stream.markdown(`**🔧 ${evt.name}** — ${JSON.stringify(evt.arguments || {}).substring(0, 120)}\n\n`);
                            } else if (evt.type === 'message' || evt.type === 'complete') {
                                stream.markdown(`**💬 ${evt.type}**: ${(evt.message || evt.content || '').substring(0, 200)}\n\n`);
                            }
                        }
                        stream.markdown(`\n*${events.events.length} events total*\n`);
                    }
                    break;
                }
                case 'fork': {
                    const parts = userMessage.trim().split(/\s+/);
                    const runId = parts[0];
                    const newReq = parts.slice(1).join(' ') || 'Continue from this point';
                    if (!runId) {
                        stream.markdown('Usage: `/fork <run-id> [new request]`\n');
                        break;
                    }
                    stream.progress(`🌿 Forking run ${runId}...`);
                    const result = await ai.forkRun(runId, newReq);
                    stream.markdown(`## 🌿 Fork Created\n\nNew run: \`${result.run_id || 'pending'}\`\nForked from: \`${runId}\`\n`);
                    break;
                }
                case 'deploy': {
                    const workspaceFolders = vscode.workspace.workspaceFolders;
                    const projectPath = userMessage.trim() || (workspaceFolders?.[0]?.uri?.fsPath) || '';
                    if (!projectPath) {
                        stream.markdown('Usage: `/deploy [path]` — Open a workspace first or specify a path.\n');
                        break;
                    }
                    stream.progress(`🚀 Deploying ${projectPath}...`);
                    const result = await ai.deployProjectToPreview(projectPath);
                    stream.markdown(`## 🚀 Deploy Complete\n\n${result.content || 'Deployed successfully.'}\n`);
                    if (result.deployUrl) {
                        stream.markdown(`\n**Preview URL:** ${result.deployUrl}\n`);
                    }
                    break;
                }
                case 'legion': {
                    if (!userMessage.trim()) {
                        stream.markdown('## ⚔️ Legion Parallel Agents\n\nUsage: `/legion task1 | task2 | task3`\n\nSeparate tasks with `|`. Each runs in a parallel V3 agent.\n');
                        break;
                    }
                    const tasks = userMessage.split('|').map(t => t.trim()).filter(Boolean);
                    stream.progress(`⚔️ Spawning ${tasks.length} parallel agents...`);
                    const result = await ai.legionSpawn(tasks);
                    stream.markdown(`## ⚔️ Legion Spawned\n\nSession: \`${result.session_id || 'pending'}\`\n${tasks.length} agents running in parallel.\n`);
                    break;
                }
                case 'seal': {
                    const runId = userMessage.trim();
                    if (!runId) {
                        stream.progress('📊 Fetching SEAL trend...');
                        const trend = await ai.fetchSEALTrend(10);
                        stream.markdown('## 📊 SEAL Quality Trend\n\n');
                        if (trend && trend.scores && trend.scores.length > 0) {
                            stream.markdown('| Run | Score | Category |\n|-----|-------|----------|\n');
                            for (const s of trend.scores) {
                                stream.markdown(`| \`${s.run_id}\` | ${s.overall_score?.toFixed(1) || '—'} | ${s.category || '—'} |\n`);
                            }
                        } else {
                            stream.markdown('No SEAL scores yet. Run agent tasks to generate scores.\n');
                        }
                    } else {
                        stream.progress(`📊 Fetching SEAL score for ${runId}...`);
                        const score = await ai.fetchSEALScore(runId);
                        stream.markdown(`## 📊 SEAL Score: \`${runId}\`\n\n`);
                        stream.markdown(`**Overall:** ${score.overall_score?.toFixed(1) || '—'}/10\n`);
                        stream.markdown(`**Category:** ${score.category || '—'}\n`);
                        if (score.dimensions) {
                            stream.markdown('\n| Dimension | Score |\n|-----------|-------|\n');
                            for (const [dim, val] of Object.entries(score.dimensions)) {
                                stream.markdown(`| ${dim} | ${typeof val === 'number' ? val.toFixed(1) : val} |\n`);
                            }
                        }
                    }
                    break;
                }
            }
        } catch (error) {
            stream.markdown(`\n\n❌ **Error:** ${error.message}\n`);
        }

        return { metadata: { mode } };
    }

    /**
     * Extract file context from chat references
     */
    async extractFileContext(request, stream) {
        const fileContext = {
            files: [],
            selectedText: null,
            workspacePath: null
        };

        // Get workspace path
        if (vscode.workspace.workspaceFolders?.[0]) {
            fileContext.workspacePath = vscode.workspace.workspaceFolders[0].uri.fsPath;
        }

        // Process references (files mentioned with # or attached)
        if (request.references && request.references.length > 0) {
            stream.progress(`📁 Reading ${request.references.length} referenced file(s)...`);
            
            for (const ref of request.references) {
                try {
                    if (ref.id === 'vscode.file' && ref.value instanceof vscode.Uri) {
                        const uri = ref.value;
                        const document = await vscode.workspace.openTextDocument(uri);
                        const content = document.getText();
                        const fileName = uri.fsPath.split('/').pop();
                        
                        // Show reference in chat
                        stream.reference(uri);
                        
                        fileContext.files.push({
                            name: fileName,
                            path: uri.fsPath,
                            content: content,
                            language: document.languageId
                        });
                        
                        console.log(`📄 [Vigthoria Chat] Read file: ${fileName} (${content.length} chars)`);
                    }
                } catch (err) {
                    console.warn(`⚠️ Failed to read reference:`, err.message);
                }
            }
        }

        // Get current editor selection if available
        const editor = vscode.window.activeTextEditor;
        if (editor && !editor.selection.isEmpty) {
            fileContext.selectedText = editor.document.getText(editor.selection);
            fileContext.selectedFile = editor.document.fileName;
            stream.reference(editor.document.uri);
        }

        return fileContext;
    }

    /**
     * Build enhanced prompt with context
     */
    buildEnhancedPrompt(message, mode, fileContext, chatHistory) {
        let prompt = '';
        
        // Add mode-specific instructions
        const modeInstructions = {
            build: `You are Vigthoria AI in BUILD mode. You help users create, modify, and analyze code.
When analyzing code, provide detailed insights with specific line references.
When creating code, generate complete, working implementations.
Always format your response with clear Markdown headings and code blocks.`,

            agent: `You are Vigthoria AI in AGENT mode. You can perform autonomous file operations.
Analyze the user's request and execute multi-step tasks.
Report each action you take and its result.
Use file paths and show what you're reading/writing.`,

            operator: `You are Vigthoria AI in OPERATOR mode. You manage system operations and orchestration.
Help with deployment, configuration, and system management tasks.
Provide step-by-step guidance for complex operations.`,

            ask: `You are Vigthoria AI. Explain the code or concept the user is asking about.
Be clear and educational in your explanations.
Use examples where helpful.`
        };
        
        prompt += modeInstructions[mode] || modeInstructions.build;
        prompt += '\n\n';
        
        // Add conversation history context
        if (chatHistory && chatHistory.length > 0) {
            prompt += '## Previous Conversation:\n';
            const recentHistory = chatHistory;
            for (const turn of recentHistory) {
                if (turn.participant === 'user') {
                    prompt += `**User:** ${turn.request?.prompt || ''}\n`;
                } else if (turn.participant === this.PARTICIPANT_ID) {
                    // Summarize AI responses to save tokens
                    const response = turn.response?.[0]?.value || '';
                    if (response.length > 200) {
                        prompt += `**Vigthoria:** ${response.substring(0, 200)}...\n`;
                    } else {
                        prompt += `**Vigthoria:** ${response}\n`;
                    }
                }
            }
            prompt += '\n';
        }
        
        // Add file context
        if (fileContext.files && fileContext.files.length > 0) {
            prompt += '## Referenced Files:\n\n';
            for (const file of fileContext.files) {
                // Limit file content to prevent token overflow
                const maxLength = 8000;
                const content = file.content.length > maxLength 
                    ? file.content.substring(0, maxLength) + '\n... (truncated)'
                    : file.content;
                    
                prompt += `### 📄 ${file.name}\n`;
                prompt += `\`\`\`${file.language || 'text'}\n${content}\n\`\`\`\n\n`;
            }
        }
        
        // Add selected text if available
        if (fileContext.selectedText) {
            prompt += '## Selected Code:\n';
            prompt += `\`\`\`\n${fileContext.selectedText}\n\`\`\`\n\n`;
        }
        
        // Add user message
        prompt += `## User Request:\n${message}\n\n`;
        
        // Add output formatting instructions
        prompt += `## Response Guidelines:
- Use clear Markdown formatting
- Include code examples in properly tagged code blocks
- Be specific and actionable
- Reference file names and line numbers when relevant
- Do NOT output JSON or tool call syntax
- Respond directly to the user's request

Your response:`;

        return prompt;
    }

    /**
     * Stream AI response using native VS Code Chat API
     */
    async streamAIResponse(prompt, mode, stream, token) {
        // Try to use VS Code's built-in language model API first
        try {
            const models = await vscode.lm.selectChatModels({
                vendor: 'copilot',
                family: 'gpt-4'
            });
            
            if (models.length > 0) {
                console.log('🔗 Using VS Code Language Model API');
                return await this.streamWithVSCodeLM(models[0], prompt, stream, token);
            }
        } catch (err) {
            console.log('ℹ️ VS Code LM API not available, using Model Router');
        }
        
        // Fall back to our Model Router
        return await this.streamWithModelRouter(prompt, mode, stream, token);
    }

    /**
     * Stream using VS Code's Language Model API (if available)
     */
    async streamWithVSCodeLM(model, prompt, stream, token) {
        const messages = [
            vscode.LanguageModelChatMessage.User(prompt)
        ];
        
        const response = await model.sendRequest(messages, {}, token);
        
        for await (const chunk of response.text) {
            if (token.isCancellationRequested) {
                stream.markdown('\n\n*Response cancelled*');
                break;
            }
            stream.markdown(chunk);
        }
    }

    /**
     * Stream using our Model Router API with real streaming
     */
    async streamWithModelRouter(prompt, mode, stream, token) {
        stream.progress('🔄 Connecting to Vigthoria AI...');
        
        // Get preferred Vigthoria native model based on mode
        const modelMap = {
            build: 'vigthoria-v3-code-30b',     // Grounded code analysis floor
            agent: 'vigthoria-v3-code-30b',     // Agent tasks require the 30B floor
            operator: 'vigthoria-v3-code-30b',  // Operator must not fall below 30B
            ask: 'vigthoria-fast-1.7b'          // Fast responses for Q&A
        };
        const model = modelMap[mode] || 'vigthoria-v3-code-30b';
        
        // Make streaming request to Model Router
        const response = await fetch(this.MODEL_ROUTER_URL, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-VS-Extension-Auth': 'vigthoria-vscode-extension-key-2025'
            },
            body: JSON.stringify({
                prompt: prompt,
                model: model,
                taskType: mode,
                service: 'smart',
                options: {
                    temperature: 0.7,
                    maxTokens: 4096,
                    stream: true  // Request streaming
                }
            })
        });

        if (!response.ok) {
            throw new Error(`Model Router error: ${response.status} ${response.statusText}`);
        }

        // Check if response is streaming
        const contentType = response.headers.get('content-type');
        
        if (contentType?.includes('text/event-stream') || contentType?.includes('application/x-ndjson')) {
            // Handle streaming response
            stream.progress('💭 Generating response...');
            
            const reader = response.body.getReader();
            const decoder = new TextDecoder();
            let buffer = '';
            
            while (true) {
                const { done, value } = await reader.read();
                
                if (done) break;
                if (token.isCancellationRequested) {
                    stream.markdown('\n\n*Response cancelled*');
                    reader.cancel();
                    break;
                }
                
                buffer += decoder.decode(value, { stream: true });
                
                // Process complete lines
                const lines = buffer.split('\n');
                buffer = lines.pop() || '';
                
                for (const line of lines) {
                    if (line.startsWith('data: ')) {
                        try {
                            const data = JSON.parse(line.slice(6));
                            if (data.response) {
                                stream.markdown(data.response);
                            }
                        } catch (e) {
                            // Raw text chunk
                            const text = line.slice(6);
                            if (text && text !== '[DONE]') {
                                stream.markdown(text);
                            }
                        }
                    }
                }
            }
        } else {
            // Handle non-streaming response (display progressively)
            stream.progress('💭 Processing response...');
            
            const data = await response.json();
            let responseText = data.response || data.content || 'No response received';
            
            // Filter out tool calls from response
            responseText = this.filterToolCalls(responseText);
            
            // Simulate streaming by breaking into chunks
            await this.simulateStreaming(responseText, stream, token);
        }
    }

    /**
     * Simulate streaming for non-streaming responses
     * Provides better UX by displaying content progressively
     */
    async simulateStreaming(text, stream, token) {
        // Split by paragraphs/sections for natural streaming
        const sections = text.split(/(\n\n|\n(?=#{1,3}\s))/);
        
        for (const section of sections) {
            if (token.isCancellationRequested) break;
            if (!section.trim()) continue;
            
            // For longer sections, stream word by word
            if (section.length > 100) {
                const words = section.split(/(\s+)/);
                let buffer = '';
                
                for (let i = 0; i < words.length; i++) {
                    if (token.isCancellationRequested) break;
                    buffer += words[i];
                    
                    // Flush buffer every 5 words or at punctuation
                    if (i % 5 === 4 || /[.!?:;,]$/.test(words[i])) {
                        stream.markdown(buffer);
                        buffer = '';
                        await this.delay(10); // Small delay for visual effect
                    }
                }
                
                if (buffer) stream.markdown(buffer);
            } else {
                stream.markdown(section);
            }
            
            await this.delay(20);
        }
    }

    /**
     * Filter out tool calls from response
     */
    filterToolCalls(text) {
        if (!text || typeof text !== 'string') return text;
        
        let filtered = text;
        
        // Remove JSON tool calls
        filtered = filtered.replace(/\{[\s\n]*"tool"[\s\n]*:[\s\S]*?\}\s*/g, '');
        filtered = filtered.replace(/```(?:json)?\s*\{[\s\S]*?"tool"[\s\S]*?\}\s*```/gmi, '');
        
        // Remove markdown tool calls
        filtered = filtered.replace(/^\s*-?\s*\*?\*?Tool\*?\*?:?\s*[a-z_]+.*$/gmi, '');
        filtered = filtered.replace(/^##\s*Parameters\s*[\s\S]*?(?=^##|\n\n\n|$)/gmi, '');
        filtered = filtered.replace(/^\s*-\s*\*\*Path\*\*:\s*\/.*$/gmi, '');
        filtered = filtered.replace(/^\s*-\s*\*\*(?:Args?|Parameters?|File)\*\*:\s*.*$/gmi, '');
        filtered = filtered.replace(/^\s*(?:⚙️?\s*)?(?:Executing|Running|Calling|Invoking):\s*.*$/gmi, '');
        filtered = filtered.replace(/^\s*(?:Allow|Approve)\??\s*\[[^\]]*\]\s*$/gmi, '');
        filtered = filtered.replace(/^Would you like me to:[\s\S]*?(?=\n\n|$)/gmi, '');
        filtered = filtered.replace(/^I can help by:[\s\S]*?(?=\n\n|$)/gmi, '');
        
        // Clean excessive newlines
        filtered = filtered.replace(/\n{3,}/g, '\n\n');
        
        return filtered.trim();
    }

    /**
     * Provide follow-up suggestions
     */
    provideFollowups(result, context) {
        const mode = result.metadata?.mode || 'build';
        
        const followups = {
            build: [
                { prompt: 'How can I improve this code?', label: '🔧 Improve', command: 'build' },
                { prompt: 'Add error handling', label: '🛡️ Add error handling', command: 'build' },
                { prompt: 'Write tests for this', label: '🧪 Write tests', command: 'build' },
                { prompt: 'Explain what this does', label: '💡 Explain', command: 'explain' }
            ],
            agent: [
                { prompt: 'Continue with the next step', label: '▶️ Continue', command: 'agent' },
                { prompt: 'What files were modified?', label: '📁 Show changes', command: 'agent' },
                { prompt: 'Undo the last change', label: '↩️ Undo', command: 'agent' }
            ],
            operator: [
                { prompt: 'Show system status', label: '📊 Status', command: 'operator' },
                { prompt: 'List running services', label: '🔌 Services', command: 'operator' },
                { prompt: 'Check logs', label: '📋 Logs', command: 'operator' }
            ]
        };
        
        return (followups[mode] || followups.build).map(f => ({
            prompt: f.prompt,
            label: f.label,
            command: f.command
        }));
    }

    delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
}

module.exports = { VigthoriaChatParticipant };
