import pandas as pd
from dataclasses import dataclass, field, asdict
from typing import List, Dict, Optional, Literal, Union
from enum import Enum
from pathlib import Path
import yaml

from ..monitoring.audit_trail import AuditRecord


class ErrorMode(Enum):
    STRICT = "strict"  # Abort on any error
    LENIENT = "lenient"  # Log and continue
    SILENT = "silent"  # Continue without logging


@dataclass
class PreprocessConfig:
    """Main configuration object for preprocessing pipeline"""

    # Rule configuration
    gui_rules: List[Dict] = field(default_factory=list)
    yaml_ruleset: Optional[str] = None
    profile: Optional[str] = None

    # Processing options
    error_mode: ErrorMode = ErrorMode.LENIENT
    enable_audit_trail: bool = True
    enable_metrics: bool = True
    chunk_size: int = 250_000

    # B2C integration - CRITICAL: Use exact existing parameter names
    strip_b2c_domains: bool = True  # Engine expects this name!
    b2c_config: Optional[Dict] = None  # GUI creates this structure

    # Domain filtering stage control
    domain_filter_stage: Literal["before_rules", "after_rules", "both"] = "after_rules"

    # Blocking configuration
    blocking_enabled: bool = True
    block_key_length: int = 3
    block_from_col: Optional[str] = None

    # Performance options
    use_parallel: bool = False
    n_jobs: int = -1

    # Feature flag for safe rollout
    use_new_preprocessing: bool = False

    # Backwards compatibility property
    @property
    def b2c_enabled(self) -> bool:
        """Alias for compatibility"""
        return self.strip_b2c_domains

    @classmethod
    def from_yaml(cls, path: Union[str, Path]) -> "PreprocessConfig":
        """Load configuration from YAML file"""
        with open(path, "r") as f:
            data = yaml.safe_load(f)
        return cls.from_dict(data)

    def to_yaml(self, path: Union[str, Path]) -> None:
        """Save configuration to YAML file"""
        data = asdict(self)
        data["error_mode"] = self.error_mode.value

        with open(path, "w") as f:
            yaml.dump(data, f, default_flow_style=False)

    @classmethod
    def from_dict(cls, data: dict) -> "PreprocessConfig":
        """Create from dictionary with validation"""
        if "error_mode" in data and isinstance(data["error_mode"], str):
            data["error_mode"] = ErrorMode(data["error_mode"])
        return cls(**data)


@dataclass
class StageMetrics:
    """Metrics for individual processing stage"""

    stage_name: str
    start_time: float
    end_time: float
    rows_modified: int
    columns_modified: List[str]
    rules_applied: int
    errors_count: int


@dataclass
class PreprocessMetrics:
    """Detailed metrics for observability"""

    start_time: float
    end_time: float
    total_rows: int
    total_columns: int
    stage_metrics: Dict[str, StageMetrics] = field(default_factory=dict)
    peak_memory_mb: float = 0.0

    # B2C specific metrics
    b2c_domains_filtered: int = 0
    b2c_fallbacks_used: int = 0

    def add_stage_metrics(self, stage: str, metrics: StageMetrics):
        self.stage_metrics[stage] = metrics


@dataclass
class PreprocessResult:
    """Result object with data and comprehensive metadata"""

    data: pd.DataFrame
    metrics: PreprocessMetrics
    audit_trail: Optional[List["AuditRecord"]] = None
    errors: List[Dict] = field(default_factory=list)
