"""Thread-safe ring buffer for span data."""
from __future__ import annotations

import logging
import threading
from collections import deque
from typing import Any

logger = logging.getLogger("fibinaci.buffer")


class MemoryBuffer:
    """Ring buffer with a max size — oldest items are dropped when full."""

    def __init__(self, max_size: int = 10_000) -> None:
        self._max_size = max_size
        self._buf: deque[dict[str, Any]] = deque(maxlen=max_size)
        self._lock = threading.Lock()
        self._overflow_warned = False

    def push(self, item: dict[str, Any]) -> None:
        with self._lock:
            if len(self._buf) == self._max_size and not self._overflow_warned:
                logger.warning(
                    "Fibinaci buffer full (%d items), dropping oldest spans. "
                    "This usually means the API is unreachable.",
                    self._max_size,
                )
                self._overflow_warned = True
            self._buf.append(item)

    def drain(self, max_items: int | None = None) -> list[dict[str, Any]]:
        """Remove and return up to max_items from the front of the buffer."""
        with self._lock:
            n = min(max_items or len(self._buf), len(self._buf))
            items = [self._buf.popleft() for _ in range(n)]
        return items

    def peek(self) -> list[dict[str, Any]]:
        """Return a copy of all items without removing them."""
        with self._lock:
            return list(self._buf)

    @property
    def size(self) -> int:
        return len(self._buf)

    def clear(self) -> None:
        with self._lock:
            self._buf.clear()
