import { IStorage } from "./storage";
import { User } from "../shared/schema";

interface ChatMessage {
    role: "system" | "user" | "assistant";
    content: string;
}

export class AiService {
    constructor(private storage: IStorage) { }

    async chat(messages: ChatMessage[], user: User, context: string): Promise<string> {
        const provider = await this.storage.getSystemSettings("ai_provider") || "openai";
        const apiKey = await this.storage.getSystemSettings("ai_api_key");
        const model = await this.storage.getSystemSettings("ai_model") || "gpt-4o";
        const baseUrl = await this.storage.getSystemSettings("ai_base_url");

        if (!apiKey && provider !== "ollama") {
            throw new Error("AI API Key not configured");
        }

        const systemPrompt = `You are TaskFlow AI, an intelligent assistant for the TaskFlow application.
You have access to the user's current tasks and context.
User Name: ${user.username}
Current Context:
${context}

Answer the user's questions based on this context. Be concise, helpful, and friendly.
If needed, suggest they create tasks or manage their schedule (you cannot perform actions yet, only advise).
`;

        const fullMessages = [
            { role: "system", content: systemPrompt },
            ...messages
        ];

        try {
            if (provider === "openai" || provider === "ollama") {
                return await this.chatOpenAI(provider, apiKey || "", model, baseUrl, fullMessages);
            } else if (provider === "anthropic") {
                return await this.chatAnthropic(apiKey || "", model, fullMessages);
            } else if (provider === "google") {
                return await this.chatGemini(apiKey || "", model, fullMessages);
            } else {
                throw new Error(`Unsupported AI provider: ${provider}`);
            }
        } catch (error: any) {
            console.error("AI Chat Error:", error);
            throw new Error(`AI Service Error: ${error.message}`);
        }
    }

    private async chatOpenAI(provider: string, apiKey: string, model: string, baseUrl: string | undefined, messages: any[]): Promise<string> {
        const url = baseUrl || (provider === "ollama" ? "http://localhost:11434/v1" : "https://api.openai.com/v1") + "/chat/completions";

        // Clean URL
        const cleanUrl = url.replace(/([^:]\/)\/+/g, "$1"); // remove double slashes

        const response = await fetch(cleanUrl, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Authorization": `Bearer ${apiKey}`,
            },
            body: JSON.stringify({
                model: model,
                messages: messages,
                temperature: 0.7,
            }),
        });

        if (!response.ok) {
            const err = await response.text();
            throw new Error(`OpenAI/Ollama API Error ${response.status}: ${err}`);
        }

        const data = await response.json();
        return data.choices[0]?.message?.content || "No response generated.";
    }

    private async chatAnthropic(apiKey: string, model: string, messages: any[]): Promise<string> {
        // Anthropic doesn't support "system" role in messages list in the same way, need to extract it
        const systemMessage = messages.find(m => m.role === "system")?.content || "";
        const userAssistantMessages = messages.filter(m => m.role !== "system");

        const response = await fetch("https://api.anthropic.com/v1/messages", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "x-api-key": apiKey,
                "anthropic-version": "2023-06-01",
            },
            body: JSON.stringify({
                model: model,
                system: systemMessage,
                messages: userAssistantMessages,
                max_tokens: 1024,
            }),
        });

        if (!response.ok) {
            const err = await response.text();
            throw new Error(`Anthropic API Error ${response.status}: ${err}`);
        }

        const data = await response.json();
        return data.content[0]?.text || "No response generated.";
    }

    private async chatGemini(apiKey: string, model: string, messages: any[]): Promise<string> {
        // Google Generative AI (Gemini)
        // POST https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=YOUR_API_KEY

        // Mapping messages to Gemini format (contents: [{ role, parts: [{ text }] }])
        // System instruction is supported in v1beta/models/...:generateContent? 
        // Gemini 1.5 Pro supports systemInstructions.
        // For simplicity, I'll prepend system prompt to first user message.

        const systemMessage = messages.find(m => m.role === "system")?.content || "";
        const contentMessages = messages.filter(m => m.role !== "system").map(m => ({
            role: m.role === "user" ? "user" : "model",
            parts: [{ text: m.content }]
        }));

        if (contentMessages.length > 0 && contentMessages[0].role === "user") {
            contentMessages[0].parts[0].text = `[System Instruction: ${systemMessage}]\n\nWait for user input... User Input: ` + contentMessages[0].parts[0].text;
        }

        const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`;

        const response = await fetch(url, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                contents: contentMessages
            }),
        });

        if (!response.ok) {
            const err = await response.text();
            throw new Error(`Gemini API Error ${response.status}: ${err}`);
        }

        const data = await response.json();
        return data.candidates?.[0]?.content?.parts?.[0]?.text || "No response generated.";
    }
}
