"""Auto-instrumentation entry point."""
from __future__ import annotations

import logging
from typing import Any

from fibinaci.instrumentation._registry import InstrumentationRegistry

logger = logging.getLogger("fibinaci.instrumentation")

_registry = InstrumentationRegistry()


def instrument(**kwargs: Any) -> None:
    """Auto-instrument all detected AI libraries.

    Patches OpenAI, Anthropic, etc. if they are installed.
    Silently skips libraries that are not available.
    Never raises — logs warnings on failure.
    """
    from fibinaci._config import FibinaciConfig
    from fibinaci._globals import init_globals

    config = FibinaciConfig(**{k: v for k, v in kwargs.items() if v is not None})
    init_globals(config)

    # Try each instrumentor — skip if library not installed
    _try_instrument("openai")
    _try_instrument("anthropic")
    _try_instrument("langchain")
    _try_instrument("llamaindex")
    _try_instrument("litellm")
    _try_instrument("cohere")
    _try_instrument("google_genai")
    _try_instrument("mistral")
    _try_instrument("bedrock")
    _try_instrument("crewai")
    _try_instrument("vercel_ai")
    _try_instrument("groq")


def _try_instrument(name: str) -> None:
    try:
        from fibinaci.instrumentation._base import BaseInstrumentor

        inst: BaseInstrumentor
        if name == "openai":
            from fibinaci.instrumentation.openai import OpenAIInstrumentor
            inst = OpenAIInstrumentor()
        elif name == "anthropic":
            from fibinaci.instrumentation.anthropic import AnthropicInstrumentor
            inst = AnthropicInstrumentor()
        elif name == "langchain":
            from fibinaci.instrumentation.langchain import LangChainInstrumentor
            inst = LangChainInstrumentor()
        elif name == "llamaindex":
            from fibinaci.instrumentation.llamaindex import LlamaIndexInstrumentor
            inst = LlamaIndexInstrumentor()
        elif name == "litellm":
            from fibinaci.instrumentation.litellm import LiteLLMInstrumentor
            inst = LiteLLMInstrumentor()
        elif name == "cohere":
            from fibinaci.instrumentation.cohere import CohereInstrumentor
            inst = CohereInstrumentor()
        elif name == "google_genai":
            from fibinaci.instrumentation.google_genai import GoogleGenAIInstrumentor
            inst = GoogleGenAIInstrumentor()
        elif name == "mistral":
            from fibinaci.instrumentation.mistral import MistralInstrumentor
            inst = MistralInstrumentor()
        elif name == "bedrock":
            from fibinaci.instrumentation.bedrock import BedrockInstrumentor
            inst = BedrockInstrumentor()
        elif name == "crewai":
            from fibinaci.instrumentation.crewai import CrewAIInstrumentor
            inst = CrewAIInstrumentor()
        elif name == "vercel_ai":
            from fibinaci.instrumentation.vercel_ai import VercelAIInstrumentor
            inst = VercelAIInstrumentor()
        elif name == "groq":
            from fibinaci.instrumentation.groq import GroqInstrumentor
            inst = GroqInstrumentor()
        else:
            return

        if not _registry.is_instrumented(name):
            inst.instrument()
            _registry.register(name, inst)
            logger.info("Instrumented %s", name)
    except ImportError:
        logger.debug("%s not installed, skipping", name)
    except Exception:
        logger.warning("Failed to instrument %s", name, exc_info=True)


def uninstrument() -> None:
    """Remove all instrumentation patches."""
    _registry.uninstrument_all()
