"""
CrashGuard Engine - Automatic routing between Polars and DuckDB.
"""
import os
from typing import Dict, Any
from datashaper.engine.polars_engine import PolarsEngine, CleanResult
from datashaper.engine.duckdb_engine import DuckDBEngine
import structlog

logger = structlog.get_logger(__name__)


class CrashGuardEngine:
    """
    Intelligent engine router with automatic fallback.
    
    Architecture:
      - Files < 1GB → Polars (fast, in-memory)
      - Files > 1GB → DuckDB (stable, out-of-core)
      - Polars OOM → Auto-retry with DuckDB
    """
    
    # File size limits by tier (in bytes)
    TIER_LIMITS = {
        "free": 25 * 1024 * 1024,           # 25 MB
        "pro": 1 * 1024 * 1024 * 1024,      # 1 GB
        "team": 5 * 1024 * 1024 * 1024,     # 5 GB
        "enterprise": float('inf')           # Unlimited
    }
    
    # Engine selection threshold
    POLARS_THRESHOLD = 1 * 1024 * 1024 * 1024  # 1 GB
    
    def __init__(self, license_info: Dict[str, Any] = None):
        self.license_info = license_info or {"tier": "free"}
        self.polars_engine = PolarsEngine()
        self.duckdb_engine = DuckDBEngine()
    
    def clean(self, file_path: str, conservative: bool = False) -> CleanResult:
        """
        Clean a file with automatic engine selection and fallback.
        
        Args:
            file_path: Path to CSV file
            conservative: Conservative cleaning mode
            
        Returns:
            CleanResult
            
        Raises:
            ValueError: If file exceeds tier limit
            Exception: If both engines fail
        """
        # Check file size
        file_size = os.path.getsize(file_path)
        tier = self.license_info.get("tier", "free")
        
        # Enforce tier limits
        tier_limit = self.TIER_LIMITS.get(tier, self.TIER_LIMITS["free"])
        if file_size > tier_limit:
            size_mb = file_size / (1024 * 1024)
            limit_mb = tier_limit / (1024 * 1024) if tier != "enterprise" else "∞"
            raise ValueError(
                f"File too large ({size_mb:.1f} MB). "
                f"{tier.upper()} tier limit: {limit_mb} MB. "
                f"Upgrade at: https://datashaper.ai/pricing"
            )
        
        # Select engine based on file size
        if file_size < self.POLARS_THRESHOLD:
            # Try Polars first (fast)
            try:
                logger.info("crashguard_routing", engine="polars", file_size=file_size)
                result = self.polars_engine.clean(file_path, conservative)
                result.engine_used = "Polars"
                return result
                
            except MemoryError as e:
                # Fallback to DuckDB
                logger.warning("polars_oom_fallback", 
                             file=file_path, 
                             error=str(e),
                             fallback="duckdb")
                
                result = self.duckdb_engine.clean(file_path, conservative)
                result.engine_used = "DuckDB (fallback)"
                return result
        else:
            # Use DuckDB for large files
            logger.info("crashguard_routing", engine="duckdb", file_size=file_size)
            result = self.duckdb_engine.clean(file_path, conservative)
            result.engine_used = "DuckDB"
            return result
