"""Langfuse API 중앙 게이트웨이.

모든 Langfuse API 호출을 단일 진입점으로 추상화합니다.
"""

import json
import logging
from datetime import datetime
from typing import Any

import sentinel.config as config

logger = logging.getLogger("sentinel.integrations.langfuse")


class LangfuseGateway:
    """Langfuse API 호출을 중앙화합니다."""

    def _client(self):
        return config.get_lf_client()

    # ------------------------------------------------------------------
    # Traces
    # ------------------------------------------------------------------

    def list_traces(
        self,
        limit: int = 20,
        name: str | None = None,
        user_id: str | None = None,
        session_id: str | None = None,
        from_timestamp: datetime | str | None = None,
        to_timestamp: datetime | str | None = None,
        tags: list[str] | None = None,
        page: int = 1,
    ) -> list[dict]:
        """트레이스 목록을 조회합니다."""
        kwargs: dict[str, Any] = {"limit": limit}
        if name:
            kwargs["name"] = name
        if user_id:
            kwargs["user_id"] = user_id
        if session_id:
            kwargs["session_id"] = session_id
        if from_timestamp:
            kwargs["from_timestamp"] = self._parse_ts(from_timestamp)
        if to_timestamp:
            kwargs["to_timestamp"] = self._parse_ts(to_timestamp)
        if tags:
            kwargs["tags"] = tags
        if page > 1:
            kwargs["page"] = page

        res = self._client().api.trace.list(**kwargs)
        data = res.data if hasattr(res, "data") else res
        return [self._trace_to_dict(t) for t in data]

    def get_trace(self, trace_id: str) -> dict:
        """단일 트레이스 상세를 조회합니다."""
        t = self._client().api.trace.get(trace_id)
        detail = self._trace_to_dict(t)
        detail["input"] = str(getattr(t, "input", ""))[:2000]
        detail["output"] = str(getattr(t, "output", ""))[:2000]
        detail["metadata"] = getattr(t, "metadata", {})
        detail["scores"] = [
            {"name": s.name, "value": s.value, "comment": getattr(s, "comment", "")}
            for s in (getattr(t, "scores", []) or [])
        ]
        detail["observations"] = [
            {
                "id": o.id,
                "type": getattr(o, "type", None),
                "name": getattr(o, "name", None),
                "model": getattr(o, "model", None),
                "latency": getattr(o, "latency", None),
                "level": getattr(o, "level", None),
            }
            for o in (getattr(t, "observations", []) or [])
        ]
        return detail

    # ------------------------------------------------------------------
    # Sessions
    # ------------------------------------------------------------------

    def list_sessions(self, limit: int = 20) -> list[dict]:
        res = self._client().api.sessions.list(limit=limit)
        data = res.data if hasattr(res, "data") else res
        return [
            {
                "id": s.id,
                "created_at": str(getattr(s, "created_at", ""))[:19],
                "trace_count": getattr(s, "count_traces", None),
            }
            for s in data
        ]

    # ------------------------------------------------------------------
    # Scores
    # ------------------------------------------------------------------

    def list_scores(
        self,
        name: str | None = None,
        limit: int = 50,
        from_timestamp: datetime | str | None = None,
        to_timestamp: datetime | str | None = None,
    ) -> list[dict]:
        kwargs: dict[str, Any] = {"limit": limit}
        if name:
            kwargs["name"] = name
        if from_timestamp:
            kwargs["from_timestamp"] = self._parse_ts(from_timestamp)
        if to_timestamp:
            kwargs["to_timestamp"] = self._parse_ts(to_timestamp)
        res = self._client().api.score_v_2.get(**kwargs)
        data = res.data if hasattr(res, "data") else res
        return [
            {
                "id": s.id,
                "name": s.name,
                "value": s.value,
                "trace_id": getattr(s, "trace_id", None),
                "comment": str(getattr(s, "comment", ""))[:200],
            }
            for s in data
        ]

    def create_score(
        self, trace_id: str, name: str, value: float, comment: str = ""
    ) -> None:
        self._client().create_score(
            trace_id=trace_id, name=name, value=value, comment=comment
        )
        self._client().flush()

    # ------------------------------------------------------------------
    # Prompts
    # ------------------------------------------------------------------

    def get_prompt(self, name: str, label: str = "production") -> dict:
        prompt = self._client().get_prompt(name, label=label, type="text")
        return {
            "name": prompt.name,
            "version": getattr(prompt, "version", None),
            "label": label,
            "prompt": prompt.prompt,
            "labels": getattr(prompt, "labels", []),
        }

    # ------------------------------------------------------------------
    # Datasets
    # ------------------------------------------------------------------

    def create_dataset(self, name: str, description: str = "") -> None:
        self._client().api.datasets.create(name=name, description=description)

    def add_dataset_item(
        self,
        dataset_name: str,
        input_data: Any,
        expected_output: str | None = None,
        source_trace_id: str | None = None,
    ) -> None:
        kwargs: dict[str, Any] = {"dataset_name": dataset_name, "input": input_data}
        if expected_output:
            kwargs["expected_output"] = expected_output
        if source_trace_id:
            kwargs["source_trace_id"] = source_trace_id
        self._client().api.dataset_items.create(**kwargs)

    # ------------------------------------------------------------------
    # Metrics
    # ------------------------------------------------------------------

    def query_metrics(self, query: dict) -> Any:
        return self._client().api.metrics.metrics(query=json.dumps(query))

    # ------------------------------------------------------------------
    # Internal helpers
    # ------------------------------------------------------------------

    @staticmethod
    def _trace_to_dict(t) -> dict:
        return {
            "id": t.id,
            "name": getattr(t, "name", None),
            "timestamp": str(getattr(t, "timestamp", ""))[:19],
            "user_id": getattr(t, "user_id", None),
            "session_id": getattr(t, "session_id", None),
            "latency": getattr(t, "latency", None),
            "total_cost": getattr(t, "total_cost", None),
            "input_tokens": getattr(t, "input_tokens", None),
            "output_tokens": getattr(t, "output_tokens", None),
            "tags": getattr(t, "tags", []),
            "level": getattr(t, "level", None),
        }

    @staticmethod
    def _parse_ts(ts) -> datetime:
        if isinstance(ts, datetime):
            return ts
        return datetime.fromisoformat(str(ts).replace("Z", "+00:00"))
