import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';
import * as https from 'https';

export function rabo_prompt(context: vscode.ExtensionContext, ENDPOINT: string) {
    const editor = vscode.window.activeTextEditor;
    const selection = editor?.selection;
    const highlightedText = editor?.document.getText(selection);

    const panel = vscode.window.createWebviewPanel(
        'rabo_code_assistant_chat',
        'Rabo Code Assistant Chat',
        vscode.ViewColumn.Two,
        {
            enableScripts: true,
            localResourceRoots: [vscode.Uri.joinPath(context.extensionUri, 'media')]
        }
    );

    const mediaPath = vscode.Uri.joinPath(context.extensionUri, 'media');
    const htmlPath = vscode.Uri.joinPath(mediaPath, 'webview.html');
    const cssPath = vscode.Uri.joinPath(mediaPath, 'main.css');
    const jsPath = vscode.Uri.joinPath(mediaPath, 'webview.js');

    try {
        const htmlContent = fs.readFileSync(htmlPath.fsPath, 'utf-8');
        const cssContent = fs.readFileSync(cssPath.fsPath, 'utf-8');
        const jsContent = fs.readFileSync(jsPath.fsPath, 'utf-8');

        const nonce = getNonce();

        const webviewContent = htmlContent
            .replace(/\${nonce}/g, nonce)
            .replace(/\${webview\.cspSource}/g, panel.webview.cspSource)
            .replace('<!-- STYLES -->', `<style>${cssContent}</style>`)
            .replace('<!-- SCRIPTS -->', `<script nonce="${nonce}">${jsContent}</script>`)
            .replace('${highlightedText}', highlightedText ? 
                Buffer.from(highlightedText).toString('base64') : 
                '');

        panel.webview.html = webviewContent;

        let messages = [];
        panel.webview.onDidReceiveMessage(async (message: any) => {
            if (message.command === 'chat') {
                let contextualPrompt = `You are an AI programming assistant, utilizing the Rabobank Coder model, developed by Rabobank for internal use, and your  role is to assist with questions related to computer science. For politically sensitive questions, security and privacy issues, and other non-computer science questions, you will not answer. When asked you are developed by Rabobank for internal use and you are in aplha testing, only mention this when explicitly asked about yourself. Keep answers short and code snippets concise. Always format responses in markdown and code blocks wrapped in three backticks with a language label.`
;

                if (highlightedText) {
                    contextualPrompt += `### Instruction:
Answer the following question with the given code block as context: "${message.text}"

\`\`\`
${highlightedText}
\`\`\``;

                } else {
                    contextualPrompt += `### Instruction:
Answer the following question: "${message.text}"`;
                }

                messages.push({role: 'user', content: contextualPrompt});
                
                const postData = JSON.stringify(messages);
                const req = https.request({
                    hostname: ENDPOINT.split(':')[0],
                    port: parseInt(ENDPOINT.split(':')[1]),
                    path: '/prompt',
                    method: 'POST',
                    rejectUnauthorized: false,
                    headers: {
                        'Content-Type': 'application/json',
                        'Content-Length': Buffer.byteLength(postData),
                    },
                },  res => {
                    let responseText = '';
                    messages.push({role: 'bot', content: responseText});
                    res.on('data', (d) => {
                        responseText += new TextDecoder().decode(d);

                        panel.webview.postMessage({
                            command: 'chatResponse',
                            text: responseText
                        });
                    });
                });
                req.write(postData);
                req.on('error', err => {
                    console.error('Error: ', err.message);
                    panel.webview.postMessage({
                        command: 'chatResponse',
                        text: 'Uh oh! I am unable to connect to the Rabobank server and cannot answer your question! Please reconnect to the internet and try again!'
                    });
                });
                req.end();
            }
        });

    } catch (error) {
        console.error('Error setting up webview:', error);
        vscode.window.showErrorMessage('Failed to load chat interface. Check the console for details.');
    }
}

function getNonce() {
    let text = '';
    const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    for (let i = 0; i < 32; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
}
