"""Tests for small utility helpers."""

from __future__ import annotations

import json
from pathlib import Path

import pytest

from src.utils import read_json, read_jsonl, records_to_frame, run_async, to_pretty_json


def test_json_helpers_round_trip_files(tmp_path: Path) -> None:
    """Read JSON and JSONL files into Python data."""
    json_path = tmp_path / "sample.json"
    jsonl_path = tmp_path / "sample.jsonl"
    json_path.write_text(json.dumps({"hello": "world"}))
    jsonl_path.write_text('{"a": 1}\n{"a": 2}\n')

    assert read_json(json_path)["hello"] == "world"
    assert read_jsonl(jsonl_path) == [{"a": 1}, {"a": 2}]


def test_display_helpers_format_records() -> None:
    """Format JSON and tabular records for notebook display."""
    pretty = to_pretty_json({"a": 1})
    frame = records_to_frame([{"a": 1}, {"a": 2}])

    assert '"a": 1' in pretty
    assert list(frame["a"]) == [1, 2]


def test_run_async_runs_without_active_loop() -> None:
    """Run a coroutine to completion outside notebook loops."""

    async def sample() -> str:
        """Return a small asynchronous result."""
        return "done"

    assert run_async(sample()) == "done"


def test_run_async_raises_inside_active_loop() -> None:
    """Reject coroutine execution when an event loop is already running."""

    async def sample() -> str:
        """Return a small asynchronous result."""
        return "done"

    async def runner() -> None:
        """Assert the helper fails inside an active loop."""
        coro = sample()
        try:
            with pytest.raises(RuntimeError):
                run_async(coro)
        finally:
            coro.close()

    run_async(runner())
