"""Dataset abstraction with generic schema and configuration support.

Provides generic (engine-agnostic) classes:
- Column: Base column definition
- Schema: Base schema with columns
- SchemaFormat: Display format enum
- DatasetConfig: Configuration for any dataset
- BaseDataset: Abstract interface for all dataset types
- DataRecord: Generic record type

Engine-specific implementations (SQLiteDataset, JSONDataset, etc.) are in their respective modules.
"""

from abc import ABC, abstractmethod
from enum import StrEnum
from typing import Any

from pydantic import BaseModel, Field


class SchemaFormat(StrEnum):
    """Format options for schema display."""

    RAW = "raw"  # List of dicts
    PRETTY = "pretty"  # Formatted table


class Column(BaseModel):
    """Generic column definition that works across all engine types.
    
    Base column class for schema definitions. Engine-specific constraints
    and methods should be implemented in subclasses.
    
    Attributes:
        name: Column name
        type: Data type (format depends on engine: SQLite uses TEXT, INTEGER, REAL, etc.)
    """

    name: str = Field(..., description="Column name")
    type: str = Field(..., description="Data type (engine-specific)")


class Schema(BaseModel):
    """Generic table schema with column definitions.
    
    Base schema class that works across all engine types (SQLite, DuckDB, Lance, Qdrant, etc).
    
    Attributes:
        columns: List of Column definitions
    """

    columns: list[Column] = Field(...)



class DatasetConfig(BaseModel):
    """Dataset configuration.
    
    Attributes:
        engine: Database engine ("sqlite", "duckdb", "lance", "qdrant", etc.)
        table_name: Name of the table/collection in the database
        in_memory: Whether to use in-memory database
        description: Optional description of the dataset
    """

    engine: str = Field(default="sqlite", description="Database engine")
    table_name: str = Field(..., description="Table name in the database")
    in_memory: bool = Field(default=True, description="Use in-memory storage")
    description: str = Field(default="", description="Dataset description")


class BaseDataset(ABC):
    """Abstract base class for all dataset types.
    
    Implementations must handle engine-specific connection creation
    and data loading. Properties and methods defined here form the
    public dataset interface.
    """

    @property
    @abstractmethod
    def engine(self) -> str:
        """Get the database engine name (sqlite, json, duckdb, lance, qdrant, etc.)."""
        ...

    @property
    @abstractmethod
    def table_name(self) -> str:
        """Get the table/collection name."""
        ...

    @abstractmethod
    def fetch_all(self) -> list[dict[str, Any]]:
        """Return all rows as a list of plain dicts with string keys.

        This is the engine-agnostic row retrieval method used by
        ``tasks_from_eval_dataset()`` and any other caller that needs
        rows without writing engine-specific query code.

        Returns:
            List of dicts where each dict represents one row and keys are
            column/field names as strings.
        """
        ...


