"""Unit tests for batcher core behavior."""

from __future__ import annotations

import pathlib
import sys
import unittest


ROOT = pathlib.Path(__file__).resolve().parents[1]
SRC = ROOT / "src"
if str(SRC) not in sys.path:
    sys.path.insert(0, str(SRC))

from vedatrace.batching.batcher import Batcher
from vedatrace.models import LogLevel, LogRecord


def _make_record(message: str) -> LogRecord:
    return LogRecord.create(
        level=LogLevel.INFO,
        message=message,
        service="orders",
        timestamp="2026-02-19T17:42:47.957694Z",
        metadata={},
    )


class TestBatcherUnit(unittest.TestCase):
    def test_add_increases_size(self) -> None:
        batcher = Batcher(batch_size=2, on_flush=lambda records: None)

        should_flush = batcher.add(_make_record("one"))

        self.assertFalse(should_flush)
        self.assertEqual(batcher.size(), 1)

    def test_add_returns_true_at_threshold(self) -> None:
        batcher = Batcher(batch_size=2, on_flush=lambda records: None)

        first = batcher.add(_make_record("one"))
        second = batcher.add(_make_record("two"))

        self.assertFalse(first)
        self.assertTrue(second)
        self.assertEqual(batcher.size(), 2)

    def test_flush_empties_buffer_and_calls_on_flush(self) -> None:
        captured: list[list[LogRecord]] = []

        def on_flush(records: list[LogRecord]) -> None:
            captured.append(records)

        batcher = Batcher(batch_size=10, on_flush=on_flush)
        batcher.add(_make_record("one"))
        batcher.add(_make_record("two"))

        batcher.flush()

        self.assertEqual(batcher.size(), 0)
        self.assertEqual(len(captured), 1)
        self.assertEqual([r.message for r in captured[0]], ["one", "two"])

    def test_flush_swallows_on_flush_exceptions(self) -> None:
        def raising_on_flush(records: list[LogRecord]) -> None:
            raise RuntimeError("flush callback failed")

        batcher = Batcher(batch_size=1, on_flush=raising_on_flush)
        batcher.add(_make_record("one"))

        batcher.flush()

        self.assertEqual(batcher.size(), 0)
