"""
senzib.utils.debug

Простые утилиты для отладки и измерения времени:

- time_block(...) как контекст-менеджер.
- @timeit(...) как декоратор.
- pretty_json(...) для красивой печати JSON-структур.
"""

from __future__ import annotations

import json
import time
from contextlib import contextmanager
from typing import Any, Callable, TypeVar, cast

from .log import get_logger

logger = get_logger("debug")

F = TypeVar("F", bound=Callable[..., Any])


@contextmanager
def time_block(label: str) -> Any:
    """
    Измеряет время выполнения блока кода.

    Пример:

        with time_block("fetch_leads"):
            do_something()

    В логгер "senzib.debug" пишет:
        [INFO] ... fetch_leads took 0.123s
    """
    start = time.perf_counter()
    try:
        yield
    finally:
        duration = time.perf_counter() - start
        logger.info("%s took %.3fs", label, duration)


def timeit(label: str | None = None) -> Callable[[F], F]:
    """
    Декоратор для измерения времени выполнения функции.

    Пример:

        @timeit("load_leads")
        def load_leads():
            ...

        @timeit()  # label по имени функции
        def foo():
            ...

    """
    def decorator(func: F) -> F:
        name = label or func.__name__

        def wrapper(*args: Any, **kwargs: Any) -> Any:
            start = time.perf_counter()
            try:
                return func(*args, **kwargs)
            finally:
                duration = time.perf_counter() - start
                logger.info("%s took %.3fs", name, duration)

        return cast(F, wrapper)

    return decorator


def pretty_json(data: Any, *, indent: int = 2, ensure_ascii: bool = False) -> str:
    """
    Возвращает красивую JSON-строку для отладки.

    :param data: любой сериализуемый объект.
    :param indent: отступы.
    :param ensure_ascii: как в json.dumps.
    """
    return json.dumps(data, indent=indent, ensure_ascii=ensure_ascii)
