"""
Emission factor database for converting activity data to CO2 equivalents.
Factors are based on EPA and DEFRA published conversion rates.
"""

from .models import EmissionCategory, EmissionScope


class EmissionFactorDB:
    """
    Database of emission factors for converting business activities to CO2 equivalents.
    Each factor represents kg CO2e per unit of activity.
    """

    # Emission factors: kg CO2e per unit
    _factors = {
        EmissionCategory.ELECTRICITY: {
            "kwh": 0.417,        # kg CO2 per kWh (US average grid)
            "mwh": 417.0,        # kg CO2 per MWh
        },
        EmissionCategory.NATURAL_GAS: {
            "therms": 5.3,       # kg CO2 per therm
            "cubic_meters": 2.0, # kg CO2 per cubic meter
            "kwh": 0.184,        # kg CO2 per kWh
        },
        EmissionCategory.TRANSPORTATION: {
            "km_car": 0.21,      # kg CO2 per km (average car)
            "km_van": 0.25,      # kg CO2 per km (van)
            "km_truck": 0.90,    # kg CO2 per km (heavy truck)
            "litres_petrol": 2.31,  # kg CO2 per litre petrol
            "litres_diesel": 2.68,  # kg CO2 per litre diesel
            "km_rail": 0.041,    # kg CO2 per km (rail freight)
        },
        EmissionCategory.WASTE: {
            "kg_landfill": 0.587,     # kg CO2 per kg to landfill
            "kg_recycled": 0.021,     # kg CO2 per kg recycled
            "kg_composted": 0.010,    # kg CO2 per kg composted
            "kg_incinerated": 0.021,  # kg CO2 per kg incinerated
        },
        EmissionCategory.WATER: {
            "cubic_meters": 0.344,    # kg CO2 per cubic meter
            "litres": 0.000344,       # kg CO2 per litre
        },
        EmissionCategory.BUSINESS_TRAVEL: {
            "km_domestic_flight": 0.246,    # kg CO2 per km
            "km_short_haul_flight": 0.156,  # kg CO2 per km
            "km_long_haul_flight": 0.195,   # kg CO2 per km
            "km_taxi": 0.21,               # kg CO2 per km
            "hotel_night": 31.1,            # kg CO2 per night
        },
        EmissionCategory.REFRIGERANTS: {
            "kg_r410a": 2088.0,   # kg CO2e per kg R-410A
            "kg_r134a": 1430.0,   # kg CO2e per kg R-134a
            "kg_r404a": 3922.0,   # kg CO2e per kg R-404A
        },
    }

    # Mapping of categories to GHG Protocol scopes
    _scope_mapping = {
        EmissionCategory.ELECTRICITY: EmissionScope.SCOPE_2,
        EmissionCategory.NATURAL_GAS: EmissionScope.SCOPE_1,
        EmissionCategory.TRANSPORTATION: EmissionScope.SCOPE_1,
        EmissionCategory.WASTE: EmissionScope.SCOPE_3,
        EmissionCategory.WATER: EmissionScope.SCOPE_3,
        EmissionCategory.BUSINESS_TRAVEL: EmissionScope.SCOPE_3,
        EmissionCategory.REFRIGERANTS: EmissionScope.SCOPE_1,
    }

    def get_factor(self, category: EmissionCategory, unit: str) -> float:
        """
        Get the emission factor for a given category and unit.
        Returns kg CO2e per unit of activity.
        Raises ValueError if category or unit not found.
        """
        if category not in self._factors:
            raise ValueError(f"Unknown emission category: {category}")
        category_factors = self._factors[category]
        if unit not in category_factors:
            available = list(category_factors.keys())
            raise ValueError(
                f"Unknown unit '{unit}' for {category.value}. Available: {available}"
            )
        return category_factors[unit]

    def get_scope(self, category: EmissionCategory) -> EmissionScope:
        """Get the GHG Protocol scope for a given emission category."""
        return self._scope_mapping.get(category, EmissionScope.SCOPE_3)

    def get_available_units(self, category: EmissionCategory) -> list:
        """Get available units for a given emission category."""
        if category not in self._factors:
            return []
        return list(self._factors[category].keys())

    def get_all_categories(self) -> list:
        """Get all available emission categories."""
        return list(self._factors.keys())

    def calculate_co2(self, category: EmissionCategory, quantity: float, unit: str) -> float:
        """
        Calculate CO2 equivalent emissions for a given activity.
        Returns kg CO2e.
        """
        factor = self.get_factor(category, unit)
        return round(quantity * factor, 4)
