# kybernis/runtime.py
from __future__ import annotations
import uuid
from functools import lru_cache
from typing import Optional

from .client import KybernisClient
from .context import kyb_run_id, kyb_span_id

def _must_uuid(s: str) -> str:
    return str(uuid.UUID(s.strip()))

@lru_cache(maxsize=1)
def kyb_client() -> KybernisClient:
    return KybernisClient()

def resolve_run_id_from_invocation_id(invocation_id: str) -> str:
    """
    Given ADK invocation_id, return Kybernis run UUID (string).
    Does NOT store invocation_id anywhere; only uses it to get/create the run.
    """
    invocation_id = (invocation_id or "").strip()
    if not invocation_id:
        raise RuntimeError("missing invocation_id; cannot resolve Kybernis run")

    existing = kyb_run_id.get()
    if existing:
        return _must_uuid(existing)

    client = kyb_client()
    run_id = client.get_or_create_run(input_context_ref=invocation_id)
    run_id = _must_uuid(run_id)
    kyb_run_id.set(run_id)
    return run_id

def ensure_span_id() -> str:
    sp = kyb_span_id.get()
    if sp:
        return sp
    sp = f"sp_{uuid.uuid4().hex}"
    kyb_span_id.set(sp)
    return sp