from __future__ import annotations

import logging
import uuid

import httpx
from pydantic import BaseModel, Field

logger = logging.getLogger("sentinely.events")


# ---------------------------------------------------------------------------
# Data model
# ---------------------------------------------------------------------------

class SentinelyEvent(BaseModel):
    event_id: str = Field(default_factory=lambda: str(uuid.uuid4()))
    org_id: str
    agent_id: str
    session_id: str
    event_type: str         # "action_allowed", "action_flagged", "action_blocked",
                            # "memory_quarantined", "injection_detected"
    tool_name: str | None
    tool_params: dict | None
    risk_score: int | None
    reason: str | None
    attack_type: str | None
    decision: str | None
    task_hash: str
    action_chain: list[dict]
    timestamp: str          # ISO 8601


# ---------------------------------------------------------------------------
# Emitter
# ---------------------------------------------------------------------------

class EventEmitter:
    """Buffer events locally or POST them to the Sentinely API."""

    def __init__(self, api_key: str | None, api_url: str, env: str) -> None:
        self.api_key = api_key
        self.api_url = api_url
        self.env = env
        self._queue: list[SentinelyEvent] = []

    async def emit(self, event: SentinelyEvent) -> None:
        if self.env == "development" or not self.api_key:
            self._queue.append(event)
            print(
                f"[SENTINELY] {event.event_type} | "
                f"risk={event.risk_score} | {event.reason}"
            )
            return

        try:
            async with httpx.AsyncClient() as client:
                await client.post(
                    f"{self.api_url}/api/v1/events",
                    json=event.model_dump(),
                    headers={"Authorization": f"Bearer {self.api_key}"},
                    timeout=1.0,
                )
        except Exception as exc:
            # Never crash the agent, but warn so operators can detect pipeline issues.
            logger.warning(
                "sentinely.events: failed to emit event %s: %s",
                event.event_type,
                exc,
            )

    def get_local_queue(self) -> list[SentinelyEvent]:
        return self._queue.copy()
