"""
Automatic schema detection from datasets.
"""

from pathlib import Path

import pandas as pd
import polars as pl

from app.core.logging import get_logger
from app.domain.models.ir import ColumnSchema, DatasetSchema

logger = get_logger(__name__)


class SchemaDetector:
    """Automatically detect dataset schema."""

    def __init__(self):
        """Initialize detector."""
        self.logger = logger

    def detect_schema(self, df: pd.DataFrame | pl.DataFrame) -> DatasetSchema:
        """Detect schema from DataFrame."""
        columns = []

        # Convert to pandas for detection if needed
        if isinstance(df, pl.DataFrame):
            df_pandas = df.to_pandas()
        else:
            df_pandas = df

        for column in df_pandas.columns:
            col_schema = self._detect_column_schema(df_pandas, column)
            columns.append(col_schema)

        return DatasetSchema(columns=columns)

    def _detect_column_schema(self, df: pd.DataFrame, column: str) -> ColumnSchema:
        """Detect schema for a single column."""
        col_data = df[column]
        
        # Detect data type
        dtype = self._map_dtype(col_data.dtype)
        
        # Check if nullable
        nullable = bool(col_data.isna().any())
        
        # Check if unique
        unique = bool(col_data.nunique() == len(col_data))
        
        # Get min/max for numeric columns
        min_value = None
        max_value = None
        if pd.api.types.is_numeric_dtype(col_data):
            if not col_data.isna().all():
                min_value = float(col_data.min())
                max_value = float(col_data.max())

        return ColumnSchema(
            name=column,
            dtype=dtype,
            nullable=nullable,
            unique=unique,
            min_value=min_value,
            max_value=max_value,
        )

    def _map_dtype(self, pandas_dtype: Any) -> str:
        """Map pandas dtype to standard type string."""
        dtype_str = str(pandas_dtype)
        
        if "int" in dtype_str:
            return "int64"
        elif "float" in dtype_str:
            return "float64"
        elif "bool" in dtype_str:
            return "bool"
        elif "datetime" in dtype_str:
            return "datetime64"
        elif "object" in dtype_str or "string" in dtype_str:
            return "string"
        else:
            return dtype_str


from typing import Any
