"""
Data models for data processing operations.

Models used by DataProcessingService to represent processing configurations,
dataset information, and processing results.
"""

from dataclasses import dataclass
from typing import List, Tuple, Optional, Dict, Any
from pathlib import Path
import polars as pl


@dataclass
class DatasetConfig:
    """Configuration for dataset processing."""
    dataset_name: str
    providers: List[str]
    required_months: List[str]
    stage_overrides: Optional[Dict[str, str]] = None
    
    def has_stage_override(self, provider: str) -> bool:
        """Check if provider has stage override."""
        return self.stage_overrides and provider in self.stage_overrides
    
    def get_stage_override(self, provider: str) -> Optional[str]:
        """Get stage override for provider."""
        if self.has_stage_override(provider):
            return self.stage_overrides[provider]
        return None


@dataclass
class CBFProcessingConfig:
    """Configuration for CBF processing."""
    mapping_path: Optional[Path] = None
    required_columns: Optional[List[str]] = None
    
    def has_custom_mapping(self) -> bool:
        """Check if custom CBF mapping is provided."""
        return self.mapping_path is not None


@dataclass
class ProcessingResult:
    """Result of data processing operations."""
    processed_data: pl.DataFrame
    original_row_count: int
    processed_row_count: int
    processing_type: str  # "generated" or "adhoc"
    cbf_columns_applied: List[str] = None
    sanitization_applied: bool = False
    error_message: Optional[str] = None
    
    def is_successful(self) -> bool:
        """Check if processing was successful."""
        return self.error_message is None and not self.processed_data.is_empty()
    
    def has_data_loss(self) -> bool:
        """Check if processing resulted in data loss."""
        return self.processed_row_count < self.original_row_count
    
    def get_row_retention_rate(self) -> float:
        """Get percentage of rows retained after processing."""
        if self.original_row_count == 0:
            return 0.0
        return (self.processed_row_count / self.original_row_count) * 100