"""
Instructor integration for Risicare SDK.

Patches instructor.from_provider() and Instructor.create() to create spans
around structured extraction attempts. Also supports legacy instructor.patch().

Span Hierarchy:
    instructor.create/{response_model}       [INTERNAL, span_kind="extraction"]
      openai.chat.completions.create/{model}  [LLM_CALL — from provider patch]
      instructor.retry/{attempt}              [INTERNAL — only on validation failure]

Does NOT suppress provider instrumentation — Instructor delegates to the
underlying LLM client, so provider patches create the LLM spans naturally
as children of the Instructor extraction span.

Usage (automatic — zero config):
    import risicare
    risicare.init(api_key="rsk-...")
    import instructor
    client = instructor.from_provider("openai/gpt-4o")
    result = client.create(response_model=User, messages=[...])  # Traced
"""

from __future__ import annotations

import logging
import threading
from typing import Any

logger = logging.getLogger(__name__)

_instrumented = False
_lock = threading.RLock()


def instrument_instructor(module: Any) -> None:
    """
    Apply instrumentation to Instructor module.

    Called by the import hook system when `instructor` is imported.
    """
    global _instrumented
    if _instrumented:
        return

    with _lock:
        if _instrumented:
            return
        _instrumented = True
        try:
            from risicare.integrations._base import check_version_compatibility

            check_version_compatibility("instructor")

            from risicare.integrations.instructor._patches import patch_instructor

            patch_instructor(module)
            logger.debug("Instrumented Instructor")
        except Exception as e:
            _instrumented = False
            logger.debug(f"Failed to instrument Instructor: {e}")
