"""CSV column profiling for template binding."""

from __future__ import annotations

import csv
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
from typing import Dict, Iterable, List, Optional


@dataclass
class ColumnProfile:
    name: str
    inferred_type: str
    semantic_types: List[str]
    cardinality: int
    nullable: bool
    null_count: int
    sample_values: List[str]


def _parse_date(value: str) -> Optional[datetime]:
    try:
        return datetime.fromisoformat(value)
    except Exception:
        pass

    for fmt in ("%Y-%m-%d", "%m/%d/%Y", "%Y/%m/%d"):
        try:
            return datetime.strptime(value, fmt)
        except Exception:
            continue
    return None


def _is_int(value: str) -> bool:
    try:
        int(value)
        return True
    except Exception:
        return False


def _is_float(value: str) -> bool:
    try:
        float(value)
        return True
    except Exception:
        return False


def _infer_type(values: Iterable[str]) -> tuple[str, List[str]]:
    has_value = False
    all_int = True
    all_float = True
    all_date = True

    for raw in values:
        value = (raw or "").strip()
        if value == "":
            continue
        has_value = True
        if not _is_int(value):
            all_int = False
        if not _is_float(value):
            all_float = False
        if _parse_date(value) is None:
            all_date = False

    if not has_value:
        return "text", ["string"]
    if all_int:
        return "int", ["numeric", "integer"]
    if all_float:
        return "float", ["numeric", "float"]
    if all_date:
        return "date", ["date"]
    return "text", ["string"]


def analyze_csv_columns(csv_path: Path, sample_size: int = 1000) -> List[ColumnProfile]:
    """Analyze CSV columns for type inference and cardinality."""
    with csv_path.open(newline="", encoding="utf-8") as handle:
        reader = csv.DictReader(handle)
        if not reader.fieldnames:
            raise ValueError("CSV file has no header row")
        fieldnames = reader.fieldnames
        samples: Dict[str, List[str]] = {name: [] for name in fieldnames}
        null_counts: Dict[str, int] = {name: 0 for name in fieldnames}

        for idx, row in enumerate(reader):
            for name in fieldnames:
                value = (row.get(name) or "").strip()
                if value == "":
                    null_counts[name] += 1
                else:
                    samples[name].append(value)
            if idx + 1 >= sample_size:
                break

    profiles: List[ColumnProfile] = []
    for name in fieldnames:
        values = samples[name]
        inferred_type, semantic_types = _infer_type(values)
        unique_values = set(values)
        profiles.append(
            ColumnProfile(
                name=name,
                inferred_type=inferred_type,
                semantic_types=semantic_types,
                cardinality=len(unique_values),
                nullable=null_counts[name] > 0,
                null_count=null_counts[name],
                sample_values=values[:10],
            )
        )
    return profiles


__all__ = ["ColumnProfile", "analyze_csv_columns"]
