"""Schema detection, validation, and merging across CSV files."""
import logging

logger = logging.getLogger(__name__)


def _merge_schema_entries(
    schemas: list[dict],
) -> tuple[dict[str, str], list[str]]:
    """Merge multiple schema dicts, raising on type conflicts.

    Returns a single {name: dtype} dict.  If a column appears in multiple
    files with different dtypes the *last* non-null dtype wins (with a
    warning embedded in the result).
    """
    merged: dict[str, str] = {}
    conflicts: list[str] = []
    for s in schemas:
        for name, dtype in s.items():
            if name in merged and merged[name] != dtype:
                conflicts.append(name)
            merged[name] = dtype  # last wins
    return merged, conflicts


def validate_schemas(schemas: list[dict], strict: bool = True) -> None:
    """Compare schemas across files and raise or warn on column mismatch.

    Checks that every file has the same set of column names.  Type
    differences across files are **not** considered an error (Polars can
    cast), but differences in *column sets* are.

    Args:
        schemas: List of ``{column_name: dtype_string}`` dicts, one per file.
        strict: If ``True`` (default), raise :class:`ValueError` on any
            column mismatch.  If ``False``, log a warning instead.
    """
    if not schemas:
        return

    col_sets = [set(s.keys()) for s in schemas]
    reference = col_sets[0]

    for i, cs in enumerate(col_sets[1:], start=1):
        only_in_ref = reference - cs
        only_in_current = cs - reference
        if only_in_ref or only_in_current:
            msg_parts = []
            if only_in_ref:
                msg_parts.append(f"File #{i} missing columns: {sorted(only_in_ref)}")
            if only_in_current:
                msg_parts.append(f"File #{i} has extra columns: {sorted(only_in_current)}")
            full_msg = f"Schema mismatch: {'; '.join(msg_parts)}"
            if strict:
                raise ValueError(full_msg)
            else:
                logger.warning(full_msg)
