"""Data cleaning helpers: numeric coercion for string columns."""
import polars as pl


def _coerce_to_float(series: pl.Series) -> pl.Series:
    """Convert string series to Float64.

    Every entry that doesn't parse as a valid float becomes null.
    Handles blank strings, standalone '+'/'-', 'N/A', 'null', 'None', etc.
    """
    series = series.cast(pl.Utf8).str.strip_chars()
    artifacts = ('', '+', '-', '.', '..', 'N/A', 'n/a', 'NA', 'null', 'None', 'NULL', '?', '---', '--', '/')
    is_artifact = series.is_in(pl.Series(artifacts).implode())
    result = []
    for v, bad in zip(series.to_list(), is_artifact.to_list()):
        if v is None or bad:
            result.append(None)
        else:
            # Check for "+"/"-" prefix artifacts (e.g., "+abc", "-xyz")
            # where the value isn't a genuine numeric string.  Values like
            # "+5" or "-3.14" are still accepted as valid floats below.
            if len(v) > 1 and v[0] in '+-':
                try:
                    float(v[1:])  # validate suffix minus prefix
                except ValueError:
                    result.append(None)
                    continue
            try:
                result.append(float(v))
            except (ValueError, TypeError):
                result.append(None)
    return pl.Series(result, dtype=pl.Float64)
