"""
Pricing calculation service following Single Responsibility Principle.
"""

from typing import List, Tuple
import polars as pl


class PricingCalculator:
    """
    Single responsibility: Calculate cost-per-unit rates from export data.

    Handles Operation 2 of export processing: computing accurate pricing rates
    for usage allocation calculations using real billing data.
    """

    # Fields for grouping pricing calculations (same 7 as combinations)
    PRICING_GROUP_FIELDS = [
        "cloud_provider",
        "service",
        "usage_family",
        "resource_type",
        "operation",
        "usage_type",
        "instance_type"
    ]

    def calculate_pricing_rates(self, export_df: pl.DataFrame) -> pl.DataFrame:
        """
        Calculate cost-per-unit rates from export data.

        Groups identical combinations and calculates cost_per_unit = total_cost / total_usage
        for each unique combination.

        Args:
            export_df: Normalized export DataFrame with pricing data

        Returns:
            DataFrame with pricing rates for each unique combination
        """
        # Filter to records with valid pricing data
        valid_pricing_df = self._filter_valid_pricing_data(export_df)

        if valid_pricing_df.is_empty():
            return self._create_empty_pricing_result()

        # Get available grouping fields
        available_group_fields = self._get_available_group_fields(valid_pricing_df)

        # Group by combination fields + pricing_unit and aggregate
        grouping_fields = available_group_fields + ["pricing_unit"]

        pricing_rates = valid_pricing_df.group_by(grouping_fields).agg([
            pl.col("usage_amount").sum().alias("total_usage"),
            pl.col("real_cost").sum().alias("total_cost")
        ]).with_columns([
            # Calculate cost per unit
            (pl.col("total_cost") / pl.col("total_usage")).alias("cost_per_unit"),
            # Mark as having pricing
            pl.lit(True).alias("has_pricing")
        ])

        # Remove intermediate aggregation columns
        final_columns = available_group_fields + [
            "pricing_unit", "cost_per_unit", "has_pricing"
        ]

        return pricing_rates.select(final_columns)

    def _filter_valid_pricing_data(self, df: pl.DataFrame) -> pl.DataFrame:
        """Filter to records with valid pricing data for calculations."""
        required_columns = ["pricing_unit", "real_cost", "usage_amount"]
        missing_columns = [col for col in required_columns if col not in df.columns]

        if missing_columns:
            return pl.DataFrame()

        return df.filter(
            (pl.col("pricing_unit").is_not_null()) &
            (pl.col("pricing_unit") != "") &
            (pl.col("real_cost") > 0) &
            (pl.col("usage_amount") > 0)
        )

    def _get_available_group_fields(self, df: pl.DataFrame) -> List[str]:
        """Get grouping fields that exist in the DataFrame."""
        return [
            field for field in self.PRICING_GROUP_FIELDS
            if field in df.columns
        ]

    def _create_empty_pricing_result(self) -> pl.DataFrame:
        """Create empty result with proper schema."""
        schema = {field: pl.Utf8 for field in self.PRICING_GROUP_FIELDS}
        schema.update({
            "pricing_unit": pl.Utf8,
            "cost_per_unit": pl.Float64,
            "has_pricing": pl.Boolean
        })

        return pl.DataFrame(schema=schema)

    def count_pricing_records(self, export_df: pl.DataFrame) -> int:
        """Count records with valid pricing data."""
        valid_pricing_df = self._filter_valid_pricing_data(export_df)
        return valid_pricing_df.height

    def validate_pricing_quality(self, pricing_df: pl.DataFrame) -> dict:
        """
        Validate quality of pricing calculations.

        Returns:
            Dictionary with validation statistics
        """
        if pricing_df.is_empty():
            return {
                "total_pricing_combinations": 0,
                "avg_cost_per_unit": 0.0,
                "min_cost_per_unit": 0.0,
                "max_cost_per_unit": 0.0,
                "suspicious_rates": []
            }

        total_combinations = pricing_df.height
        cost_stats = pricing_df.select([
            pl.col("cost_per_unit").mean().alias("avg"),
            pl.col("cost_per_unit").min().alias("min"),
            pl.col("cost_per_unit").max().alias("max")
        ]).to_dicts()[0]

        # Flag suspiciously high or low rates
        suspicious = pricing_df.filter(
            (pl.col("cost_per_unit") > 1000.0) |  # Very expensive
            (pl.col("cost_per_unit") < 0.001)     # Very cheap
        )

        return {
            "total_pricing_combinations": total_combinations,
            "avg_cost_per_unit": cost_stats["avg"] or 0.0,
            "min_cost_per_unit": cost_stats["min"] or 0.0,
            "max_cost_per_unit": cost_stats["max"] or 0.0,
            "suspicious_rates": suspicious.to_dicts() if suspicious.height > 0 else []
        }