import sys
import threading
import time


class Spinner:
    """Simple CLI spinner for long-running commands."""

    def __init__(
        self,
        message: str,
        enabled: bool = True,
        interval: float = 0.1,
        min_duration: float = 0.0,
    ) -> None:
        self._message = message
        self._enabled = enabled and sys.stderr.isatty()
        self._interval = interval
        self._min_duration = min_duration
        self._stop_event = threading.Event()
        self._thread: threading.Thread | None = None
        self._start_time: float | None = None

    def __enter__(self) -> "Spinner":
        if self._enabled:
            self._start_time = time.perf_counter()
            self._thread = threading.Thread(target=self._spin, daemon=True)
            self._thread.start()
        return self

    def __exit__(self, exc_type, exc, tb) -> bool:
        if self._enabled:
            self._stop_event.set()
            if self._thread:
                self._thread.join()
            if self._start_time is not None and self._min_duration > 0:
                elapsed = time.perf_counter() - self._start_time
                if elapsed < self._min_duration:
                    time.sleep(self._min_duration - elapsed)
            self._clear_line()
        return False

    def _spin(self) -> None:
        frames = ["-", "\\", "|", "/"]
        idx = 0
        while not self._stop_event.is_set():
            frame = frames[idx % len(frames)]
            sys.stderr.write(f"\r{frame} {self._message}")
            sys.stderr.flush()
            time.sleep(self._interval)
            idx += 1

    def _clear_line(self) -> None:
        padding = " " * (len(self._message) + 2)
        sys.stderr.write(f"\r{padding}\r")
        sys.stderr.flush()
