"""Multi-provider AI service router - all requests go through Eden.ai."""

from typing import Optional, Dict
import asyncio
from ..config import load_config, get_eden_api_key, get_provider_settings, get_system_prompt


def _run_async(coro):
    """Helper to run async code synchronously, handling nested loops."""
    try:
        # Check if there's already a running loop
        loop = asyncio.get_running_loop()
        # If we're in an async context, use nest_asyncio or run in thread
        import concurrent.futures
        with concurrent.futures.ThreadPoolExecutor() as executor:
            future = executor.submit(asyncio.run, coro)
            return future.result(timeout=120)
    except RuntimeError:
        # No running loop, safe to create one
        return asyncio.run(coro)


def get_eden_key_or_error():
    """Get Eden API key or raise descriptive error."""
    api_key = get_eden_api_key()
    if not api_key:
        raise ValueError("Eden.ai API key not configured. Set it in Settings → Eden.ai tab.")
    return api_key


def analyze_with_provider(
    text: str,
    analysis_type: str = "comprehensive",
    provider: str = None
) -> dict:
    """
    Analyze text using Eden.ai with the configured provider.

    Args:
        text: Text to analyze
        analysis_type: Type of analysis
        provider: Override provider (uses settings if None)

    Returns:
        Analysis results including topics
    """
    api_key = get_eden_key_or_error()

    if provider is None:
        settings = get_provider_settings()
        provider = settings.get("analysis_provider", "openai")

    from .eden_ai import chat_with_eden

    # Map provider names to Eden provider strings
    eden_provider = _map_to_eden_provider(provider)

    # Get the system prompt from config (user-configurable)
    system_prompt = get_system_prompt("analysis_full")

    # First, get the main analysis
    messages = [{
        "role": "user",
        "content": f"""{system_prompt}

--- TRANSCRIPTION START ---
{text[:8000]}
--- TRANSCRIPTION END ---"""
    }]

    result = _run_async(chat_with_eden(messages, api_key, providers=[eden_provider]))

    # Extract response from Eden format
    analysis_text = _extract_eden_response(result)

    # Now extract topics separately for better tagging
    topics = _extract_topics(text, api_key, eden_provider)

    return {
        "analysis": analysis_text,
        "topics": topics,
        "provider": provider,
        "via": "eden",
        "cost_info": result.get("cost_info")
    }


def _extract_topics(text: str, api_key: str, provider: str) -> list:
    """
    Extract topics/tags from text.
    Returns a list of 3-7 topic strings.
    """
    from .eden_ai import chat_with_eden

    # Get the system prompt from config (user-configurable)
    system_prompt = get_system_prompt("analysis_topics")

    messages = [{
        "role": "user",
        "content": f"""{system_prompt}

Transcription:
{text[:4000]}"""
    }]

    try:
        result = _run_async(chat_with_eden(messages, api_key, providers=[provider], max_tokens=200))
        response_text = _extract_eden_response(result)

        # Parse topics from response
        topics = []
        for line in response_text.strip().split('\n'):
            line = line.strip()
            # Remove any numbering, bullets, or dashes
            line = line.lstrip('0123456789.-•*) ').strip()
            if line and len(line) < 50:  # Reasonable topic length
                topics.append(line)

        return topics[:7]  # Max 7 topics
    except Exception as e:
        print(f"Topics extraction failed: {e}")
        return []


def critique_with_provider(
    text: str,
    original_analysis: str,
    provider: str = None
) -> str:
    """
    Critique an analysis using Eden.ai with the configured provider.

    Args:
        text: Original transcription
        original_analysis: The analysis to critique
        provider: Override provider (uses settings if None)

    Returns:
        Critique text
    """
    api_key = get_eden_key_or_error()

    if provider is None:
        settings = get_provider_settings()
        provider = settings.get("critique_provider", "anthropic")

    from .eden_ai import chat_with_eden

    eden_provider = _map_to_eden_provider(provider)

    # Get the system prompt from config (user-configurable)
    system_prompt = get_system_prompt("critique_main")

    messages = [{
        "role": "user",
        "content": f"""{system_prompt}

Original Transcription (excerpt):
--- TRANSCRIPTION START ---
{text[:3000]}
--- TRANSCRIPTION END ---

Analysis to critique:
{original_analysis}"""
    }]

    result = _run_async(chat_with_eden(messages, api_key, providers=[eden_provider]))
    return _extract_eden_response(result)


def find_resources_with_provider(
    topic: str,
    context: str = None,
    provider: str = None
) -> dict:
    """
    Find external resources using Eden.ai with the configured provider.

    Args:
        topic: Topic to search for
        context: Optional context from transcription
        provider: Override provider (uses settings if None)

    Returns:
        Resources and references with citations
    """
    api_key = get_eden_key_or_error()

    if provider is None:
        settings = get_provider_settings()
        provider = settings.get("resources_provider", "perplexityai")

    # Use specialized Perplexity search for citations
    if provider == "perplexity" or provider == "perplexityai":
        from .eden_ai import search_with_perplexity

        # Get the system prompt from config (user-configurable)
        system_prompt = get_system_prompt("resources_search")

        query = f"""{system_prompt}

Topic: {topic}"""

        result = _run_async(search_with_perplexity(query, api_key, context))

        return {
            "resources": result.get("answer", ""),
            "citations": result.get("citations", []),
            "provider": "perplexityai",
            "via": "eden",
            "topic": topic
        }

    # For other providers, use chat
    from .eden_ai import chat_with_eden

    eden_provider = _map_to_eden_provider(provider)

    # Get the system prompt from config (user-configurable)
    system_prompt = get_system_prompt("resources_search")

    query = f"{system_prompt}\n\nTopic: {topic}"
    if context:
        query += f"\n\nContext from the content:\n{context[:1500]}"

    messages = [{"role": "user", "content": query}]

    result = _run_async(chat_with_eden(messages, api_key, providers=[eden_provider]))
    response_text = _extract_eden_response(result)

    return {
        "resources": response_text,
        "provider": provider,
        "via": "eden",
        "topic": topic
    }


def answer_question_with_provider(
    text: str,
    question: str,
    provider: str = None
) -> dict:
    """
    Answer a question using Eden.ai with the configured provider.

    Args:
        text: Transcription text
        question: User's question
        provider: Override provider (uses settings if None)

    Returns:
        Answer and metadata
    """
    api_key = get_eden_key_or_error()

    if provider is None:
        settings = get_provider_settings()
        provider = settings.get("analysis_provider", "openai")

    from .eden_ai import chat_with_eden

    eden_provider = _map_to_eden_provider(provider)

    # Get the system prompt from config (user-configurable)
    system_prompt = get_system_prompt("qa_answer")

    messages = [{
        "role": "user",
        "content": f"""{system_prompt}

--- TRANSCRIPTION START ---
{text[:8000]}
--- TRANSCRIPTION END ---

Question: {question}"""
    }]

    result = _run_async(chat_with_eden(messages, api_key, providers=[eden_provider]))
    answer = _extract_eden_response(result)

    return {"answer": answer, "provider": provider, "via": "eden"}


def comprehensive_qa(
    text: str,
    question: str,
    find_references: bool = True
) -> dict:
    """
    Comprehensive Q&A with optional critique and references.
    All requests go through Eden.ai.

    Args:
        text: Transcription text
        question: User's question
        find_references: Whether to find external references

    Returns:
        Complete Q&A response with all provider results
    """
    settings = get_provider_settings()
    result = {}

    # 1. Get initial answer from analysis provider
    try:
        answer_result = answer_question_with_provider(text, question)
        result["initial_answer"] = answer_result
    except Exception as e:
        result["initial_answer_error"] = str(e)

    # 2. Get critique from critique provider (if different from analysis)
    if settings.get("critique_provider") != settings.get("analysis_provider"):
        try:
            initial_answer = result.get("initial_answer", {}).get("answer", "")
            if initial_answer:
                critique = critique_with_provider(text, initial_answer)
                result["critique"] = critique
        except Exception as e:
            result["critique_error"] = str(e)

    # 3. Find external references if requested
    if find_references:
        try:
            resources = find_resources_with_provider(question, text[:2000])
            result["references"] = resources
        except Exception as e:
            result["references_error"] = str(e)

    return result


def _map_to_eden_provider(provider: str) -> str:
    """Map our provider names to Eden.ai provider strings."""
    mapping = {
        # Analysis/Chat providers
        "openai": "openai",
        "anthropic": "anthropic",
        "google": "google",
        "cohere": "cohere",
        "meta": "meta",
        "perplexity": "perplexityai",  # Perplexity for web search & citations
        "perplexityai": "perplexityai",
        # Transcription providers
        "assemblyai": "assemblyai",
        "deepgram": "deepgram",
        "amazon": "amazon",
        "microsoft": "microsoft",
    }
    return mapping.get(provider, "openai")


def _extract_eden_response(result: dict) -> str:
    """Extract the text response from Eden.ai result format."""
    if not result:
        return "No response received"

    # Eden returns results keyed by provider name
    for provider_name, provider_result in result.items():
        if isinstance(provider_result, dict):
            # Try different response formats
            if 'generated_text' in provider_result:
                return provider_result['generated_text']
            if 'message' in provider_result:
                return provider_result['message']
            if 'text' in provider_result:
                return provider_result['text']

    # Fallback: return string representation
    return str(result)
