import threading
import logging
from typing import Any, Dict, List, Optional
import requests
from telona.types import MonitorEvent, MonitorResponse

logger = logging.getLogger("telona")
DEFAULT_ENDPOINT = "https://hwdxxskiieatzdcurugv.supabase.co/functions/v1/ingest"

class Telona:
    def __init__(self, api_key: str, endpoint: Optional[str] = None, async_mode: bool = True, timeout: float = 10.0):
        if not api_key:
            raise ValueError("api_key is required")
        self.api_key = api_key
        self.endpoint = endpoint or DEFAULT_ENDPOINT
        self.async_mode = async_mode
        self.timeout = timeout
        self._session = requests.Session()
        self._session.headers.update({
            "Content-Type": "application/json",
            "x-api-key": self.api_key,
        })

    def monitor(self, query: str, response: Optional[str] = None, model: Optional[str] = None,
                prompt: Optional[str] = None, retrieved_docs: Optional[List[Dict[str, Any]]] = None,
                tokens_used: Optional[int] = None, prompt_tokens: Optional[int] = None,
                completion_tokens: Optional[int] = None, latency_ms: Optional[float] = None,
                cost: Optional[float] = None, hallucination_score: Optional[float] = None,
                retrieval_score: Optional[float] = None, relevance_score: Optional[float] = None,
                experiment_id: Optional[str] = None, variant_id: Optional[str] = None,
                metadata: Optional[Dict[str, Any]] = None) -> Optional[MonitorResponse]:
        event = MonitorEvent(
            query=query, response=response, model=model, prompt=prompt,
            retrieved_docs=retrieved_docs, tokens_used=tokens_used,
            prompt_tokens=prompt_tokens, completion_tokens=completion_tokens,
            latency_ms=latency_ms, cost=cost, hallucination_score=hallucination_score,
            retrieval_score=retrieval_score, relevance_score=relevance_score,
            experiment_id=experiment_id, variant_id=variant_id, metadata=metadata or {},
        )
        return self._send(event.to_dict())

    def monitor_batch(self, events: List[Dict[str, Any]]) -> Optional[MonitorResponse]:
        return self._send(events)

    def _send(self, payload: Any) -> Optional[MonitorResponse]:
        if self.async_mode:
            threading.Thread(target=self._do_send, args=(payload,), daemon=True).start()
            return None
        return self._do_send(payload)

    def _do_send(self, payload: Any) -> MonitorResponse:
        try:
            resp = self._session.post(self.endpoint, json=payload, timeout=self.timeout)
            if resp.status_code == 200:
                data = resp.json()
                return MonitorResponse(success=True, count=data.get("count", 0), ids=data.get("ids", []))
            else:
                error_msg = resp.json().get("error", resp.text)
                logger.error(f"Telona ingest failed ({resp.status_code}): {error_msg}")
                return MonitorResponse(success=False, error=error_msg)
        except Exception as e:
            logger.error(f"Telona ingest error: {e}")
            return MonitorResponse(success=False, error=str(e))

    def close(self): self._session.close()
    def __enter__(self): return self
    def __exit__(self, *args): self.close()
