import * as https from 'https';
import * as http from 'http';
import { ChatMessage, AIConfig, AIResponse, ToolDefinition, ToolCall } from '../common/types';

export class AntCompatClient {

    async chat(
        messages: ChatMessage[],
        config: AIConfig,
        tools?: ToolDefinition[],
        onChunk?: (content: string) => void
    ): Promise<AIResponse> {
        const url = new URL(`${config.baseUrl}/v1/messages`);
        const isHttps = url.protocol === 'https:';
        const mod = isHttps ? https : http;

        // Anthropic uses a separate `system` parameter
        const systemMsg = messages.find(m => m.role === 'system');
        const chatMessages = messages
            .filter(m => m.role !== 'system')
            .map(m => {
                if (m.role === 'tool') {
                    return {
                        role: 'user',
                        content: [{
                            type: 'tool_result',
                            tool_use_id: m.toolCallId,
                            content: m.content
                        }]
                    };
                }
                if (m.toolCalls && m.toolCalls.length > 0) {
                    const content: Record<string, unknown>[] = [];
                    if (m.content) {
                        content.push({ type: 'text', text: m.content });
                    }
                    for (const tc of m.toolCalls) {
                        content.push({
                            type: 'tool_use',
                            id: tc.id,
                            name: tc.name,
                            input: JSON.parse(tc.arguments || '{}')
                        });
                    }
                    return { role: 'assistant', content };
                }
                return { role: m.role, content: m.content };
            });

        const bodyObj: Record<string, unknown> = {
            model: config.model,
            max_tokens: config.maxTokens,
            temperature: config.temperature,
            messages: chatMessages,
            stream: true
        };
        if (systemMsg) {
            bodyObj.system = systemMsg.content;
        }
        if (tools && tools.length > 0) {
            bodyObj.tools = tools.map(t => ({
                name: t.name,
                description: t.description,
                input_schema: t.parameters
            }));
        }

        const body = JSON.stringify(bodyObj);

        return new Promise<AIResponse>((resolve, reject) => {
            const req = mod.request(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'x-api-key': config.apiKey,
                    'anthropic-version': '2023-06-01',
                    'Accept': 'text/event-stream'
                }
            }, (res) => {
                if (res.statusCode !== 200) {
                    let errBody = '';
                    res.on('data', (chunk: Buffer) => { errBody += chunk.toString(); });
                    res.on('end', () => reject(new Error(`API error ${res.statusCode}: ${errBody}`)));
                    return;
                }

                let fullContent = '';
                let buffer = '';
                // Track tool use blocks
                const toolCalls: ToolCall[] = [];
                let currentToolIndex = -1;

                res.on('data', (chunk: Buffer) => {
                    buffer += chunk.toString();
                    const lines = buffer.split('\n');
                    buffer = lines.pop() || '';

                    for (const line of lines) {
                        const trimmed = line.trim();
                        if (!trimmed || !trimmed.startsWith('data: ')) continue;
                        let data: string;
                        try {
                            data = JSON.parse(trimmed.slice(6));
                        } catch { continue; }
                        const parsed = typeof data === 'string' ? JSON.parse(data) : data;

                        if (parsed.type === 'content_block_start') {
                            if (parsed.content_block?.type === 'tool_use') {
                                currentToolIndex = toolCalls.length;
                                toolCalls.push({
                                    id: parsed.content_block.id,
                                    name: parsed.content_block.name,
                                    arguments: ''
                                });
                            }
                        } else if (parsed.type === 'content_block_delta') {
                            if (parsed.delta?.type === 'text_delta' && parsed.delta.text) {
                                fullContent += parsed.delta.text;
                                if (onChunk) onChunk(parsed.delta.text);
                            } else if (parsed.delta?.type === 'input_json_delta' && parsed.delta.partial_json) {
                                if (currentToolIndex >= 0 && currentToolIndex < toolCalls.length) {
                                    toolCalls[currentToolIndex].arguments += parsed.delta.partial_json;
                                }
                            }
                        } else if (parsed.type === 'content_block_stop') {
                            currentToolIndex = -1;
                        }
                    }
                });

                res.on('end', () => {
                    onChunk?.('');
                    resolve({ content: fullContent, toolCalls });
                });

                res.on('error', reject);
            });

            req.on('error', reject);
            req.write(body);
            req.end();
        });
    }
}