"""
Quality validation service following Single Responsibility Principle.
"""

from dataclasses import dataclass
from typing import List, Dict, Any
import polars as pl


@dataclass
class QualityWarning:
    """Represents a data quality warning."""
    type: str
    severity: str  # 'low', 'medium', 'high'
    message: str
    count: int
    details: Dict[str, Any]


class QualityValidator:
    """
    Single responsibility: Validate data quality for export processing.

    Identifies suspicious patterns and data quality issues in export data
    and pricing calculations.
    """

    def validate_pricing_calculations(self, pricing_df: pl.DataFrame) -> List[QualityWarning]:
        """
        Validate quality of pricing calculations.

        Args:
            pricing_df: DataFrame with calculated pricing rates

        Returns:
            List of quality warnings
        """
        warnings = []

        if pricing_df.is_empty():
            return warnings

        # Check for suspiciously high rates
        high_rates = pricing_df.filter(pl.col("cost_per_unit") > 1000.0)
        if high_rates.height > 0:
            warnings.append(QualityWarning(
                type="high_pricing_rates",
                severity="medium",
                message=f"Found {high_rates.height} combinations with very high cost per unit (>$1000)",
                count=high_rates.height,
                details={"max_rate": high_rates.select(pl.col("cost_per_unit").max()).item()}
            ))

        # Check for suspiciously low rates
        low_rates = pricing_df.filter(pl.col("cost_per_unit") < 0.001)
        if low_rates.height > 0:
            warnings.append(QualityWarning(
                type="low_pricing_rates",
                severity="low",
                message=f"Found {low_rates.height} combinations with very low cost per unit (<$0.001)",
                count=low_rates.height,
                details={"min_rate": low_rates.select(pl.col("cost_per_unit").min()).item()}
            ))

        # Check for zero or negative rates
        invalid_rates = pricing_df.filter(pl.col("cost_per_unit") <= 0)
        if invalid_rates.height > 0:
            warnings.append(QualityWarning(
                type="invalid_pricing_rates",
                severity="high",
                message=f"Found {invalid_rates.height} combinations with zero or negative cost per unit",
                count=invalid_rates.height,
                details={}
            ))

        return warnings

    def validate_combination_uniqueness(self, combinations: pl.DataFrame) -> List[QualityWarning]:
        """
        Validate uniqueness of service combinations.

        Args:
            combinations: DataFrame with service combinations

        Returns:
            List of quality warnings
        """
        warnings = []

        if combinations.is_empty():
            return warnings

        # Check for missing critical fields
        critical_fields = ["cloud_provider", "service", "resource_type"]
        for field in critical_fields:
            if field in combinations.columns:
                missing_values = combinations.filter(
                    (pl.col(field).is_null()) |
                    (pl.col(field) == "")
                ).height

                if missing_values > 0:
                    warnings.append(QualityWarning(
                        type="missing_critical_field",
                        severity="high",
                        message=f"Found {missing_values} combinations with missing {field}",
                        count=missing_values,
                        details={"field": field}
                    ))

        # Check for provider distribution
        if "cloud_provider" in combinations.columns:
            provider_counts = combinations.group_by("cloud_provider").agg([
                pl.len().alias("count")
            ])

            single_provider_count = provider_counts.filter(pl.col("count") == 1).height
            total_providers = provider_counts.height

            if single_provider_count > total_providers * 0.5:
                warnings.append(QualityWarning(
                    type="uneven_provider_distribution",
                    severity="low",
                    message=f"Many providers ({single_provider_count}) have only single combinations",
                    count=single_provider_count,
                    details={"total_providers": total_providers}
                ))

        return warnings

    def validate_export_completeness(self, export_df: pl.DataFrame) -> List[QualityWarning]:
        """
        Validate completeness of export data.

        Args:
            export_df: Raw export DataFrame

        Returns:
            List of quality warnings
        """
        warnings = []

        if export_df.is_empty():
            warnings.append(QualityWarning(
                type="empty_export",
                severity="high",
                message="Export file contains no data",
                count=0,
                details={}
            ))
            return warnings

        # Check for very small exports
        if export_df.height < 10:
            warnings.append(QualityWarning(
                type="small_export",
                severity="medium",
                message=f"Export contains only {export_df.height} records",
                count=export_df.height,
                details={}
            ))

        # Check for missing pricing data
        pricing_cols = ["Real Cost", "Usage Amount", "Pricing Unit"]
        available_pricing_cols = [col for col in pricing_cols if col in export_df.columns]

        if len(available_pricing_cols) < len(pricing_cols):
            missing_cols = [col for col in pricing_cols if col not in export_df.columns]
            warnings.append(QualityWarning(
                type="missing_pricing_columns",
                severity="medium",
                message=f"Export missing pricing columns: {missing_cols}",
                count=len(missing_cols),
                details={"missing_columns": missing_cols}
            ))

        return warnings

    def generate_quality_summary(self, warnings: List[QualityWarning]) -> Dict[str, Any]:
        """
        Generate summary of quality validation results.

        Args:
            warnings: List of quality warnings

        Returns:
            Summary dictionary with quality metrics
        """
        if not warnings:
            return {
                "overall_quality": "excellent",
                "total_warnings": 0,
                "high_severity": 0,
                "medium_severity": 0,
                "low_severity": 0
            }

        severity_counts = {"high": 0, "medium": 0, "low": 0}
        for warning in warnings:
            severity_counts[warning.severity] += 1

        # Determine overall quality
        if severity_counts["high"] > 0:
            overall_quality = "poor"
        elif severity_counts["medium"] > 2:
            overall_quality = "fair"
        elif severity_counts["medium"] > 0:
            overall_quality = "good"
        else:
            overall_quality = "excellent"

        return {
            "overall_quality": overall_quality,
            "total_warnings": len(warnings),
            "high_severity": severity_counts["high"],
            "medium_severity": severity_counts["medium"],
            "low_severity": severity_counts["low"]
        }