import axios from 'axios';
import { config } from '../config/index.js';
import logger from '../utils/logger.js';

export type AIProvider = 'openai' | 'perplexity' | 'gemini';

export interface AIProviderHealth {
    provider: AIProvider;
    configured: boolean;
    model: string;
    inFallbackList: boolean;
    fallbackIndex: number | null;
    status: 'configured' | 'missing_key' | 'ok' | 'error';
    message: string;
}

export class AIClient {
    public async generateAnalysis(prompt: string): Promise<string | null> {
        const fallbackList = config.AI.FALLBACK_LIST;

        for (const provider of fallbackList) {
            try {
                logger.info(`[AI] Attempting analysis with provider: ${provider}...`);
                let result: string | null = null;

                switch (provider) {
                    case 'openai':
                        result = await this.callOpenAI(prompt);
                        break;
                    case 'perplexity':
                        result = await this.callPerplexity(prompt);
                        break;
                    case 'gemini':
                        result = await this.callGemini(prompt);
                        break;
                    default:
                        logger.warn(`[AI] Unsupported provider in fallback list: ${provider}`);
                        continue;
                }

                if (result) {
                    logger.info(`[AI] Successfully generated analysis using ${provider}.`);
                    return result;
                }
            } catch (error: any) {
                logger.error(`[AI] Provider ${provider} failed: ${error.message}`);
                // Continue to next provider in fallback list
            }
        }

        logger.error('[AI] All providers in fallback list failed or were not configured.');
        return null;
    }

    public async getProviderHealth(probe: boolean = false): Promise<AIProviderHealth[]> {
        const fallbackList = config.AI.FALLBACK_LIST;
        const providers: AIProvider[] = ['openai', 'perplexity', 'gemini'];

        const results: AIProviderHealth[] = [];
        for (const provider of providers) {
            const configured = this.isProviderConfigured(provider);
            const model = this.resolveModel(provider);
            const fallbackIndex = fallbackList.indexOf(provider);
            const inFallbackList = fallbackIndex >= 0;

            if (!configured) {
                results.push({
                    provider,
                    configured: false,
                    model,
                    inFallbackList,
                    fallbackIndex: inFallbackList ? fallbackIndex : null,
                    status: 'missing_key',
                    message: 'API key missing'
                });
                continue;
            }

            if (!probe) {
                results.push({
                    provider,
                    configured: true,
                    model,
                    inFallbackList,
                    fallbackIndex: inFallbackList ? fallbackIndex : null,
                    status: 'configured',
                    message: 'Configured (probe skipped)'
                });
                continue;
            }

            try {
                await this.probeProvider(provider);
                results.push({
                    provider,
                    configured: true,
                    model,
                    inFallbackList,
                    fallbackIndex: inFallbackList ? fallbackIndex : null,
                    status: 'ok',
                    message: 'Provider probe succeeded'
                });
            } catch (error: any) {
                results.push({
                    provider,
                    configured: true,
                    model,
                    inFallbackList,
                    fallbackIndex: inFallbackList ? fallbackIndex : null,
                    status: 'error',
                    message: error?.message || 'Provider probe failed'
                });
            }
        }

        return results;
    }

    private isProviderConfigured(provider: AIProvider): boolean {
        switch (provider) {
            case 'openai':
                return !!config.AI.OPENAI_API_KEY;
            case 'perplexity':
                return !!config.AI.PERPLEXITY_API_KEY;
            case 'gemini':
                return !!config.AI.GEMINI_API_KEY;
            default:
                return false;
        }
    }

    private resolveModel(provider: AIProvider): string {
        switch (provider) {
            case 'openai':
                return config.AI.MODEL.includes('gpt') ? config.AI.MODEL : 'gpt-4o-mini';
            case 'perplexity':
                return config.AI.MODEL.includes('sonar') ? config.AI.MODEL : 'sonar';
            case 'gemini':
                return config.AI.MODEL.includes('gemini') ? config.AI.MODEL : 'gemini-1.5-flash';
            default:
                return config.AI.MODEL;
        }
    }

    private async probeProvider(provider: AIProvider): Promise<void> {
        const probePrompt = 'Return JSON: {"action":"HOLD","confidence":0,"reasoning":"probe"}';
        let response: string | null = null;

        switch (provider) {
            case 'openai':
                response = await this.callOpenAI(probePrompt);
                break;
            case 'perplexity':
                response = await this.callPerplexity(probePrompt);
                break;
            case 'gemini':
                response = await this.callGemini(probePrompt);
                break;
            default:
                throw new Error(`Unsupported provider: ${provider}`);
        }

        if (!response || !String(response).trim()) {
            throw new Error('Empty response from provider');
        }
    }

    private async callOpenAI(prompt: string): Promise<string | null> {
        const apiKey = config.AI.OPENAI_API_KEY;
        if (!apiKey) return null;

        const model = config.AI.MODEL.includes('gpt') ? config.AI.MODEL : 'gpt-4o-mini';

        const response = await axios.post(
            'https://api.openai.com/v1/chat/completions',
            {
                model: model,
                messages: [
                    { role: 'system', content: 'You are an expert crypto trading assistant. strictly output JSON.' },
                    { role: 'user', content: prompt }
                ],
                temperature: 0.2
            },
            {
                headers: {
                    'Authorization': `Bearer ${apiKey}`,
                    'Content-Type': 'application/json'
                },
                timeout: 10000
            }
        );
        return response.data.choices[0].message.content;
    }

    private async callPerplexity(prompt: string): Promise<string | null> {
        const apiKey = config.AI.PERPLEXITY_API_KEY;
        if (!apiKey) return null;

        const model = config.AI.MODEL.includes('sonar') ? config.AI.MODEL : 'sonar';

        const response = await axios.post(
            'https://api.perplexity.ai/chat/completions',
            {
                model: model,
                messages: [
                    { role: 'system', content: 'You are an expert crypto trading assistant. Strictly output JSON.' },
                    { role: 'user', content: prompt }
                ],
                temperature: 0.2
            },
            {
                headers: {
                    'Authorization': `Bearer ${apiKey}`,
                    'Content-Type': 'application/json'
                },
                timeout: 10000
            }
        );
        return response.data.choices[0].message.content;
    }

    private async callGemini(prompt: string): Promise<string | null> {
        const apiKey = config.AI.GEMINI_API_KEY;
        if (!apiKey) return null;

        const model = config.AI.MODEL.includes('gemini') ? config.AI.MODEL : 'gemini-1.5-flash';
        const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`;

        const response = await axios.post(url, {
            contents: [{
                parts: [{ text: `You are an expert crypto trading assistant. Strictly output JSON.\n\n${prompt}` }]
            }]
        }, { timeout: 10000 });

        return response.data.candidates[0].content.parts[0].text;
    }
}
