"""Gatekeeper helpers for persisting inbound pipeline trigger events."""

from __future__ import annotations

from dataclasses import dataclass
import hashlib
import json
from typing import Any, Optional

from .ontology_manager import OntologyManager
from .pipeline_states_store import PipelineStateStore


@dataclass(frozen=True)
class EventIngestResult:
    event_id: str
    pipeline_id: str
    dedupe_key: Optional[str]
    created: bool


def _stable_payload_text(payload: Any) -> str:
    if payload is None:
        payload = {}
    return json.dumps(payload, sort_keys=True, separators=(",", ":"))


def build_event_dedupe_key(
    *,
    pipeline_id: str,
    event_type: str,
    source: str,
    payload: Any = None,
    source_event_id: Optional[str] = None,
) -> str:
    payload_text = _stable_payload_text(payload)
    src_event = source_event_id or ""
    raw = "\n".join([pipeline_id, event_type, source, src_event, payload_text])
    return hashlib.sha256(raw.encode("utf-8")).hexdigest()


def emit_pipeline_event(
    *,
    pipeline_id: str,
    event_type: str,
    source: str = "external",
    payload: Any = None,
    dedupe_key: Optional[str] = None,
    source_event_id: Optional[str] = None,
) -> EventIngestResult:
    norm_pipeline_id = pipeline_id.strip()
    if not norm_pipeline_id:
        raise ValueError("pipeline_id must not be empty")
    norm_event_type = event_type.strip()
    if not norm_event_type:
        raise ValueError("event_type must not be empty")
    norm_source = (source or "external").strip() or "external"
    norm_dedupe = dedupe_key.strip() if isinstance(dedupe_key, str) and dedupe_key.strip() else None
    if norm_dedupe is None:
        norm_dedupe = build_event_dedupe_key(
            pipeline_id=norm_pipeline_id,
            event_type=norm_event_type,
            source=norm_source,
            payload=payload,
            source_event_id=source_event_id,
        )

    om = OntologyManager(load_resources=False)
    store = PipelineStateStore(
        db_path=om.pipeline_states_db_path,
        semantics_dir=om._semantics_dir,
    )
    store.init_schema()
    event_id, created = store.insert_event(
        pipeline_id=norm_pipeline_id,
        event_type=norm_event_type,
        payload=payload,
        source=norm_source,
        dedupe_key=norm_dedupe,
        source_event_id=source_event_id,
    )
    return EventIngestResult(
        event_id=event_id,
        pipeline_id=norm_pipeline_id,
        dedupe_key=norm_dedupe,
        created=created,
    )
