import numpy as np


class PropertyValuation:
    """
    This is a placeholder class for the property valuation model
    """

    UPRN_VALUE_LOOKUP = {
        15038202: 202000,
        37024763: 213000,
        100070478545: 212000,
        100070297696: 662000,  # Based on Zoopla's estimation of nearby house, 8 bloomfield road
        100070476394: 222000,  # Based on Zoopla's estimation of next door, 20 Parkside
        100071264896: 128000,
        # Based on next door neighbour: https://themovemarket.com/tools/propertyprices/flat-2-queens-wood-house-219
        # -brandwood-road-birmingham-b14-6pu
    }

    # We base our valuation uplifts on a number of sources
    # https://www.moneysupermarket.com/gas-and-electricity/value-of-efficiency/
    MSM_MAPPING = [
        {"start": "G", "end": "F", "increase_percentage": 0.06},
        {"start": "F", "end": "E", "increase_percentage": 0.01},
        {"start": "E", "end": "D", "increase_percentage": 0.01},
        {"start": "D", "end": "C", "increase_percentage": 0.02},
        {"start": "C", "end": "B", "increase_percentage": 0.04},
        {"start": "B", "end": "A", "increase_percentage": 0.0},
    ]

    # https://www.lloydsbankinggroup.com/media/press-releases/2021/halifax/homebuyers-pay-a-green-premium-of-40000
    # -for-the-most-energy-efficient-properties.html
    LLOYDS_MAPPING = [
        {"start": "G", "end": "F", "increase_percentage": 0.038},
        {"start": "F", "end": "E", "increase_percentage": 0.029},
        {"start": "E", "end": "D", "increase_percentage": 0.024},
        {"start": "D", "end": "C", "increase_percentage": 0.02},
        {"start": "C", "end": "B", "increase_percentage": 0.02},
        {"start": "B", "end": "A", "increase_percentage": 0.018},
    ]

    KNIGHT_FRANK_MAPPING = [
        {"start": "D", "end": "C", "increase_percentage": 0.03},
        {"start": "D", "end": "B", "increase_percentage": 0.088},
    ]

    NATIONWIDE_MAPPING = [
        {"start": "G", "end": "D", "increase_percentage": 0.035},
        {"start": "F", "end": "D", "increase_percentage": 0.035},
        {"start": "D", "end": "B", "increase_percentage": 0.017},
        {"start": "D", "end": "A", "increase_percentage": 0.017},
    ]

    EPC_BANDS = ["G", "F", "E", "D", "C", "B", "A"]

    @classmethod
    def get_increase(cls, epc_band_range):

        increases = []
        for i in range(len(epc_band_range)):

            if i == len(epc_band_range) - 1:
                break

            current = epc_band_range[i]
            next = epc_band_range[i + 1]

            msm_increase = [x for x in cls.MSM_MAPPING if x["start"] == current and x["end"] == next][0]
            lloyds_increase = [x for x in cls.LLOYDS_MAPPING if x["start"] == current and x["end"] == next][0]

            increases.append(
                {
                    "start": current,
                    "end": next,
                    "msm_increase": msm_increase["increase_percentage"],
                    "lloyds_increase": lloyds_increase["increase_percentage"],
                }
            )

        # We now aggregate the increases. The should be compound increases so we multiply them together
        msm_increase = np.prod([1 + x["msm_increase"] for x in increases]) - 1
        lloyds_increase = np.prod([1 + x["lloyds_increase"] for x in increases]) - 1

        return msm_increase, lloyds_increase

    @classmethod
    def estimate(cls, property_instance, target_epc):
        value = cls.UPRN_VALUE_LOOKUP.get(property_instance.uprn)

        if not value:
            raise ValueError("Have not implemented valuation for this property")

        current_epc = property_instance.data["current-energy-rating"]
        # We get the spectrum of ratings between the current and target EPC
        epc_band_range = cls.EPC_BANDS[cls.EPC_BANDS.index(current_epc): cls.EPC_BANDS.index(target_epc) + 1]

        msm_increase, lloyds_increase = cls.get_increase(epc_band_range)

        # We now use the knight frank and nationwide data to get further valuation evidence, if we have it
        kf_increase = [x for x in cls.KNIGHT_FRANK_MAPPING if x["start"] == current_epc and x["end"] == target_epc]
        nw_increase = [x for x in cls.NATIONWIDE_MAPPING if x["start"] == current_epc and x["end"] == target_epc]

        kf_increase = kf_increase[0]["increase_percentage"] if kf_increase else None
        nw_increase = nw_increase[0]["increase_percentage"] if nw_increase else None

        all_increases = [x for x in [msm_increase, lloyds_increase, kf_increase, nw_increase] if x is not None]

        max_increase = max(all_increases)
        min_increase = min(all_increases)
        avg_increase = np.mean(all_increases)

        return {
            "current_value": value,
            "lower_bound_increased_value": value * (1 + min_increase),
            "upper_bound_increased_value": value * (1 + max_increase),
            "average_increased_value": value * (1 + avg_increase),
        }
