"""Safe type-coercion utilities.

Used by parsers to convert raw exchange response values (which may be
strings with commas, ``None``, empty strings, or unexpected types) into
typed Python values without raising exceptions.
"""

from __future__ import annotations

from typing import Any


def safe_int(value: Any) -> int | None:
    """Coerce *value* to ``int``, returning ``None`` on failure.

    Handles common cases returned by NSE/BSE APIs:
    - ``None`` → ``None``
    - ``""`` → ``None``
    - ``"1,23,456"`` → ``123456`` (comma-separated Indian numerals)
    - ``"23.0"`` → ``23``
    - ``-999`` → ``-999``

    Examples::

        >>> safe_int("1,23,456")
        123456
        >>> safe_int(None) is None
        True
        >>> safe_int("N/A") is None
        True
    """
    if value is None:
        return None
    if isinstance(value, int):
        return value
    if isinstance(value, float):
        return int(value)
    s = str(value).strip().replace(",", "")
    if not s or s in ("-", "N/A", "NA", "-"):
        return None
    try:
        # handle "23.0" style floats returned by some endpoints
        return int(float(s))
    except (ValueError, OverflowError):
        return None


def safe_float(value: Any) -> float | None:
    """Coerce *value* to ``float``, returning ``None`` on failure.

    Examples::

        >>> safe_float("45.67")
        45.67
        >>> safe_float("") is None
        True
        >>> safe_float(None) is None
        True
    """
    if value is None:
        return None
    if isinstance(value, float):
        return value
    if isinstance(value, int):
        return float(value)
    s = str(value).strip().replace(",", "")
    if not s or s in ("-", "N/A", "NA"):
        return None
    try:
        return float(s)
    except (ValueError, OverflowError):
        return None


def safe_int_or_zero(value: Any) -> int:
    """Like :func:`safe_int` but returns ``0`` instead of ``None``."""
    result = safe_int(value)
    return result if result is not None else 0


__all__ = ["safe_float", "safe_int", "safe_int_or_zero"]
