class AnnualBillSavings:
    """
    This is a simple class which will estimate the annual bill savings, based on the kwh savings.
    This class uses data from Ofgem, including their price caps, to provide us with an estimate for
    1KWH of energy.
    """

    # These gas an electricity consumption figures are based off of figures presented by Ofgem
    # https://www.ofgem.gov.uk/information-consumers/energy-advice-households/average-gas-and-electricity-use-explained
    AVERAGE_ELECTRICITY_CONSUMPTION = 2700
    AVERAGE_GAS_CONSUMPTION = 11500

    # Latest price cap figures from Ofgem are for January 2024
    # https://www.ofgem.gov.uk/publications/changes-energy-price-cap-1-january-2024
    ELECTRICITY_PRICE_CAP = 0.29
    GAS_PRICE_CAP = 0.07

    # This is a weighted mean of the price caps, using the consumption figures above as weights
    PRICE_FACTOR = 0.11183098591549295

    @classmethod
    def estimate(cls, kwh: float):
        """
        Estimate the annual bill savings based on the kwh savings
        :param kwh: The kwh savings
        :return: An estimate for annual bill savings
        """
        return cls.PRICE_FACTOR * kwh

    @classmethod
    def adjust_energy_to_metered(cls, epc_energy_consumption, current_epc_rating):
        """
        The over-prediction of energy use by EPCs in Great Britain: A comparison
        of EPC-modelled and metered primary energy use intensity

        Which can be found here: https://www.sciencedirect.com/science/article/pii/S0378778823002542
        We implement the results on page 10

        :return:
        """

        gradients = {
            "A": -0.1,
            "B": -0.1,
            "C": -0.43,
            "D": -0.52,
            "E": -0.7,
            "F": -0.76,
            "G": -0.76
        }

        intercepts = {
            "A": 28,
            "B": 28,
            "C": 97,
            "D": 119,
            "E": 160,
            "F": 157,
            "G": 157
        }

        gradient = gradients[current_epc_rating]
        intercept = intercepts[current_epc_rating]

        # This should be negative
        consumption_difference = gradient * epc_energy_consumption + intercept
        if consumption_difference > 0:
            raise ValueError("consumption_difference should be negative")

        adjusted_consumption = (epc_energy_consumption + consumption_difference)

        return adjusted_consumption
