import pandas as pd
from typing import Type
from ..exceptions import ColumnValidationError

# Allowed simple type mapping checkers (can be extended)
_TYPE_CHECKERS = {
    int: lambda x: isinstance(x, (int,)) and not isinstance(x, bool),
    float: lambda x: isinstance(x, (float, int)) and not isinstance(x, bool),
    str: lambda x: isinstance(x, str),
    bool: lambda x: isinstance(x, bool),
}

def _is_instance(value, expected_type: Type):
    if pd.isna(value):
        return True  # treat NaN/None as pass for type check (null check handled separately)
    checker = _TYPE_CHECKERS.get(expected_type)
    if checker:
        return checker(value)
    # fallback: use isinstance
    try:
        return isinstance(value, expected_type)
    except Exception:
        return False

def validate_type(series: pd.Series, expected_type: Type, column_name: str):
    """
    Validate that non-null values in `series` are of `expected_type`.
    Raises ColumnValidationError on failure with sample offending values.
    """
    if series is None:
        raise ColumnValidationError(column_name, "column missing", sample=[])
    mask = series.apply(lambda v: not _is_instance(v, expected_type))
    if mask.any():
        sample = series[mask].dropna().head(10).tolist()
        raise ColumnValidationError(column_name, f"type mismatch (expected {expected_type.__name__})", sample=sample)
