"""Shared fixtures for the unit suite."""

from __future__ import annotations

from pathlib import Path

import pytest
from spens import events, pricing


def _no_network(url: str, timeout: float):
    raise AssertionError(f"unit tests must not reach the network ({url})")


@pytest.fixture(autouse=True)
def isolated_pricing(tmp_path_factory, monkeypatch):
    """Keep pricing hermetic: no network, no user cache, no vendored data.

    Costing happens inside ``compute_session_summary``, so without this every
    test that writes a session summary would fetch six datasets over the
    network and its expected costs would drift with upstream prices.  Tests
    that exercise fetching opt back in by monkeypatching
    ``pricing._http_get_json`` and calling ``set_live_fetch(True)``.
    """
    monkeypatch.setenv("XDG_CACHE_HOME", str(tmp_path_factory.mktemp("pricing-cache")))
    monkeypatch.setattr(pricing, "VENDOR_DIR", Path(tmp_path_factory.mktemp("pricing-vendor")))
    monkeypatch.setattr(pricing, "_http_get_json", _no_network)
    pricing.set_live_fetch(False)
    yield
    pricing.set_live_fetch(None)
    pricing.reset_table_cache()


@pytest.fixture(autouse=True)
def _reset_active_emitter():
    """Keep the module-level emitter hermetic between tests."""
    events.reset()
    yield
    events.reset()


class RecordingSink:
    """A sink that records every event it receives, in order."""

    def __init__(self) -> None:
        self.events: list[events.Event] = []

    def on_event(self, event: events.Event) -> None:
        self.events.append(event)

    def close(self) -> None:
        pass

    def named(self) -> list[str]:
        return [e.event for e in self.events]

    def messages(self) -> list[str]:
        return [e.data["message"] for e in self.events if "message" in e.data]


@pytest.fixture
def recording_sink() -> RecordingSink:
    return RecordingSink()


@pytest.fixture
def event_capture(recording_sink: RecordingSink) -> RecordingSink:
    """Configure an active emitter delivering to a recording sink."""
    events.configure(events.Emitter("test-session", [recording_sink]))
    return recording_sink
