import pandas as pd
def safe_stratified_kfold(group_labels,
                          k_folds=10,
                          **cv_splitter_args):
    """
    Creates a StratifiedKFold splitter, raising errors for invalid inputs.

    This function ensures that the number of splits is valid for the given
    dataset, preventing silent fallbacks to different splitting strategies.

    Returns
    ------
        StratifiedKFold splitter.

    Raises
    ------
    ValueError
        If n_splits is less than 2.
    ValueError
        If n_splits is greater than the number of members in the smallest class.
    """
    from sklearn.model_selection import StratifiedKFold
    if not isinstance(group_labels, pd.Series):
        group_labels = pd.Series(group_labels)
    min_group_size = group_labels.value_counts().min()

    if k_folds < 2:
        raise ValueError(
            f"The number of folds (k_folds) must be at least 2, but got {k_folds}."
        )

    if k_folds > min_group_size:
        if min_group_size == 1:
            raise ValueError(
                f"There's at least one strata with only 1 element. Please recheck your data."
            )
        else:    
            raise ValueError(
                f"The number of folds ({k_folds}) cannot be greater than the number of "
                f"members in the smallest stratum ({min_group_size}). Please rerun using a value for "
                f"the number of folds between 2 and {min_group_size} (inclusive)."
            )

    # Instantiate the splitter and return the iterator from its .split() method
    splitter = StratifiedKFold(n_splits=k_folds, **cv_splitter_args)
    return splitter

def build_cv_folds(X_fit, y_fit, groups_fit, k_folds=10, **cv_splitter_args):
    y_series = pd.Series(y_fit, index=groups_fit.index)

    # check if target is binary
    is_binary = y_series.nunique(dropna=False) == 2

    if is_binary:
        strata = groups_fit.astype(str) + "_" + y_series.astype(str)
    else:
        strata = groups_fit.astype(str)
    
    splitter = safe_stratified_kfold(strata, k_folds=k_folds, **cv_splitter_args)
    folds = splitter.split(X_fit, strata)

    return folds