from backend.Property import Property
from recommendations.RoofRecommendations import RoofRecommendations
from recommendations.tests.test_data.materials import materials
from etl.epc.Record import EPCRecord


class TestRoofRecommendations:

    def test_loft_insulation_recommendation_no_insulation(self):
        epc_record = EPCRecord()
        epc_record.prepared_epc = {
            "county": "Cambridgeshire",
        }
        property_instance = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
        property_instance.age_band = "F"
        property_instance.insulation_floor_area = 100
        property_instance.roof = {
            'original_description': 'Pitched, no insulation (assumed)',
            'clean_description': 'Pitched, no insulation',
            'thermal_transmittance': None,
            'thermal_transmittance_unit': None,
            'is_pitched': True, 'is_roof_room': False, 'is_loft': False, 'is_flat': False, 'is_thatched': False,
            'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
            'insulation_thickness': 'none', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
        }

        roof_recommender = RoofRecommendations(property_instance=property_instance, materials=materials)

        assert not roof_recommender.recommendations

        roof_recommender.recommend(phase=0)

        assert len(roof_recommender.recommendations) == 1
        assert roof_recommender.recommendations[0]["parts"][0]["depth"] == 300

    def test_loft_insulation_recommendation_50mm_insulation(self):
        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Kent", "roof-energy-eff": "Very Poor"}
        property_instance2 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
        property_instance2.age_band = "F"
        property_instance2.insulation_floor_area = 100
        property_instance2.roof = {
            'original_description': 'Pitched, 50mm loft insulation (assumed)',
            'clean_description': 'Pitched, 50mm loft insulation',
            'thermal_transmittance': None,
            'thermal_transmittance_unit': None,
            'is_pitched': True, 'is_roof_room': False, 'is_loft': True, 'is_flat': False, 'is_thatched': False,
            'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
            'insulation_thickness': '50', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
        }

        roof_recommender2 = RoofRecommendations(property_instance=property_instance2, materials=materials)

        assert not roof_recommender2.recommendations

        roof_recommender2.recommend(phase=0)

        assert len(roof_recommender2.recommendations) == 1

        assert roof_recommender2.recommendations[0]["total"] == 1653
        assert roof_recommender2.recommendations[0]["new_u_value"] == 0.13
        assert roof_recommender2.recommendations[0]["starting_u_value"] == 0.68
        assert roof_recommender2.recommendations[0]["parts"][0]["depth"] == 300

        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Greater London Authority", "roof-energy-eff": "Very Poor"}
        property_instance3 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
        property_instance3.age_band = "F"
        property_instance3.insulation_floor_area = 100
        property_instance3.roof = {
            'original_description': 'Pitched, 50mm loft insulation (assumed)',
            'clean_description': 'Pitched, 50mm loft insulation',
            'thermal_transmittance': None,
            'thermal_transmittance_unit': None,
            'is_pitched': True, 'is_roof_room': False, 'is_loft': True, 'is_flat': False, 'is_thatched': False,
            'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
            'insulation_thickness': '50', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
        }

        roof_recommender3 = RoofRecommendations(property_instance=property_instance3, materials=materials)

        assert not roof_recommender3.recommendations

        roof_recommender3.recommend(phase=0)

        assert roof_recommender3.recommendations
        assert len(roof_recommender3.recommendations) == 1
        assert roof_recommender3.recommendations[0]["parts"][0]["depth"] == 300.0

    def test_loft_insulation_recommendation_150mm_insulation(self):
        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "North East Lincolnshire", "roof-energy-eff": "Good"}
        property_instance4 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
        property_instance4.age_band = "F"
        property_instance4.insulation_floor_area = 100
        property_instance4.roof = {
            'original_description': 'Pitched, 150mm loft insulation (assumed)',
            'clean_description': 'Pitched, 150mm loft insulation',
            'thermal_transmittance': None,
            'thermal_transmittance_unit': None,
            'is_pitched': True, 'is_roof_room': False, 'is_loft': True, 'is_flat': False, 'is_thatched': False,
            'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
            'insulation_thickness': '150', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
        }

        roof_recommender4 = RoofRecommendations(property_instance=property_instance4, materials=materials)

        assert not roof_recommender4.recommendations

        roof_recommender4.recommend(phase=0, default_u_values=True)

        assert len(roof_recommender4.recommendations) == 1

        assert roof_recommender4.recommendations[0]["total"] == 1653.0
        assert roof_recommender4.recommendations[0]["new_u_value"] == 0.14
        assert roof_recommender4.recommendations[0]["starting_u_value"] == 0.3
        assert roof_recommender4.recommendations[0]["parts"][0]["depth"] == 300

        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Somerset", "roof-energy-eff": "Good"}
        property_instance5 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
        property_instance5.age_band = "F"
        property_instance5.insulation_floor_area = 100
        property_instance5.roof = {
            'original_description': 'Pitched, 150mm loft insulation (assumed)',
            'clean_description': 'Pitched, 150mm loft insulation',
            'thermal_transmittance': None,
            'thermal_transmittance_unit': None,
            'is_pitched': True, 'is_roof_room': False, 'is_loft': True, 'is_flat': False, 'is_thatched': False,
            'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
            'insulation_thickness': '150', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
        }

        roof_recommender5 = RoofRecommendations(property_instance=property_instance5, materials=materials)

        assert not roof_recommender5.recommendations

        roof_recommender5.recommend(phase=0)

        assert roof_recommender5.recommendations
        assert len(roof_recommender5.recommendations) == 1
        assert roof_recommender5.recommendations[0]["parts"][0]["depth"] == 300

    def test_loft_insulation_recommendation_270mm_insulation(self):
        # We shouldn't recommend anything in this case
        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Portsmouth"}
        property_instance6 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
        property_instance6.age_band = "F"
        property_instance6.insulation_floor_area = 100
        property_instance6.roof = {
            'original_description': 'Pitched, 270mm loft insulation (assumed)',
            'clean_description': 'Pitched, 270mm loft insulation',
            'thermal_transmittance': None,
            'thermal_transmittance_unit': None,
            'is_pitched': True, 'is_roof_room': False, 'is_loft': True, 'is_flat': False, 'is_thatched': False,
            'is_at_rafters': False, 'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
            'insulation_thickness': '270', 'roof_thermal_transmittance': None, 'roof_insulation_thickness': 'none'
        }

        roof_recommender6 = RoofRecommendations(property_instance=property_instance6, materials=materials)

        assert not roof_recommender6.recommendations

        roof_recommender6.recommend(phase=0)

        assert len(roof_recommender6.recommendations) == 0

    def test_uninsulated_room_in_roof(self):
        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Southampton", "roof-energy-eff": "Very Poor"}
        property_instance7 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
        property_instance7.age_band = "F"
        property_instance7.insulation_floor_area = 100
        property_instance7.roof = {
            'original_description': 'Roof room(s), no insulation (assumed)',
            'clean_description': 'Roof room(s), no insulation',
            'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
            'is_roof_room': True, 'is_loft': False, 'is_flat': False, 'is_thatched': False, 'is_at_rafters': False,
            'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'none'
        }

        property_instance7.pitched_roof_area = 110

        roof_recommender7 = RoofRecommendations(property_instance=property_instance7, materials=materials)

        assert not roof_recommender7.recommendations

        roof_recommender7.recommend(phase=0)

        assert len(roof_recommender7.recommendations) == 1
        assert roof_recommender7.recommendations[0]["new_u_value"] == 0.2
        assert roof_recommender7.recommendations[0]["starting_u_value"] == 0.8
        assert roof_recommender7.recommendations[0]["description"] == "Insulate room in roof at rafters and re-decorate"

    def test_ceiling_insulated_room_in_roof(self):
        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Southampton", "roof-energy-eff": "Very Poor"}
        property_instance8 = Property(id=8, address="fake", postcode="fake", epc_record=epc_record)
        property_instance8.age_band = "F"
        property_instance8.insulation_floor_area = 100
        property_instance8.roof = {
            'original_description': 'Roof room(s), ceiling insulated',
            'clean_description': 'Roof room(s), ceiling insulated',
            'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
            'is_roof_room': True, 'is_loft': False, 'is_flat': False, 'is_thatched': False,
            'is_at_rafters': False,
            'is_assumed': False, 'has_dwelling_above': False, 'is_valid': True,
            'insulation_thickness': 'average'
        }

        property_instance8.pitched_roof_area = 110

        roof_recommender8 = RoofRecommendations(property_instance=property_instance8, materials=materials)

        assert not roof_recommender8.recommendations

        roof_recommender8.recommend(phase=0)

        # No recommendations in this case
        assert not roof_recommender8.recommendations

    def test_insulated_room_in_roof(self):
        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Southampton", "roof-energy-eff": "Very Poor"}
        property_instance9 = Property(id=9, address="fake", postcode="fake", epc_record=epc_record)
        property_instance9.age_band = "F"
        property_instance9.insulation_floor_area = 100
        property_instance9.roof = {
            'original_description': 'Roof room(s), insulated (assumed)',
            'clean_description': 'Roof room(s), insulated',
            'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
            'is_roof_room': True, 'is_loft': False, 'is_flat': False, 'is_thatched': False, 'is_at_rafters': False,
            'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'average'
        }

        property_instance9.pitched_roof_area = 110
        property_instance9.data = {"county": "Rutland"}

        roof_recommender9 = RoofRecommendations(property_instance=property_instance9, materials=materials)

        assert not roof_recommender9.recommendations

        roof_recommender9.recommend(phase=0)

        # No recommendations in this case
        assert not roof_recommender9.recommendations

    def test_limited_insulated_room_in_roof(self):
        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Westmorland", "roof-energy-eff": "Poor"}
        property_instance10 = Property(id=10, address="fake", postcode="fake", epc_record=epc_record)
        property_instance10.age_band = "F"
        property_instance10.insulation_floor_area = 100
        property_instance10.roof = {
            'original_description': 'Roof room(s), limited insulation (assumed)',
            'clean_description': 'Roof room(s), limited insulation',
            'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
            'is_roof_room': True, 'is_loft': False, 'is_flat': False, 'is_thatched': False, 'is_at_rafters': False,
            'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True,
            'insulation_thickness': 'below average'
        }

        property_instance10.pitched_roof_area = 110

        roof_recommender10 = RoofRecommendations(property_instance=property_instance10, materials=materials)

        assert not roof_recommender10.recommendations

        roof_recommender10.recommend(phase=0)

        assert len(roof_recommender10.recommendations) == 1

        assert roof_recommender10.recommendations[0]["new_u_value"] == 0.19

        assert roof_recommender10.recommendations[0]["starting_u_value"] == 0.68

        assert (roof_recommender10.recommendations[0]["description"] ==
                'Insulate room in roof at rafters and re-decorate')

    def test_flat_no_insulation(self):
        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Swindon"}
        property_instance11 = Property(id=11, address="fake", postcode="fake", epc_record=epc_record)
        property_instance11.age_band = "D"
        property_instance11.insulation_floor_area = 33.5
        property_instance11.perimeter = 24
        property_instance11.roof = {
            'original_description': 'Flat, no insulation (assumed)',
            'clean_description': 'Flat, no insulation',
            'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
            'is_roof_room': False, 'is_loft': False, 'is_flat': True, 'is_thatched': False, 'is_at_rafters': False,
            'is_assumed': True, 'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'none'
        }

        roof_recommender11 = RoofRecommendations(property_instance=property_instance11, materials=materials)

        assert not roof_recommender11.recommendations

        roof_recommender11.recommend(phase=0)

        assert len(roof_recommender11.recommendations) == 1

        assert roof_recommender11.recommendations[0]["parts"][0]["depth"] == 150
        assert roof_recommender11.recommendations[0]["total"] == 6532.5
        assert roof_recommender11.recommendations[0]["new_u_value"] == 0.14
        assert roof_recommender11.recommendations[0]["starting_u_value"] == 2.3
        assert roof_recommender11.recommendations[0]["description"] == \
               "Insulate the home's flat roof with 150mm of Ecotherm Eco-Versal General Purpose Insulation Board"

    def test_flat_insulated(self):
        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Thurrock"}
        property_instance12 = Property(id=12, address="fake", postcode="fake", epc_record=epc_record)
        property_instance12.age_band = "D"
        property_instance12.insulation_floor_area = 40
        property_instance12.perimeter = 30

        property_instance12.roof = {
            'original_description': 'Flat, insulated (assumed)',
            'clean_description': 'Flat, insulated',
            'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
            'is_roof_room': False,
            'is_loft': False, 'is_flat': True, 'is_thatched': False, 'is_at_rafters': False, 'is_assumed': True,
            'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'average'
        }

        roof_recommender12 = RoofRecommendations(property_instance=property_instance12, materials=materials)

        assert not roof_recommender12.recommendations

        roof_recommender12.recommend(phase=0)

        assert not roof_recommender12.recommendations

    def test_flat_limited_insulation(self):
        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Tyne and Wear"}
        property_instance13 = Property(id=12, address="fake", postcode="fake", epc_record=epc_record)
        property_instance13.age_band = "D"
        property_instance13.insulation_floor_area = 40
        property_instance13.perimeter = 40
        property_instance13.roof = {
            'original_description': 'Flat, limited insulation (assumed)',
            'clean_description': 'Flat, limited insulation',
            'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_pitched': False,
            'is_roof_room': False,
            'is_loft': False, 'is_flat': True, 'is_thatched': False, 'is_at_rafters': False, 'is_assumed': True,
            'has_dwelling_above': False, 'is_valid': True, 'insulation_thickness': 'below average'
        }

        roof_recommender13 = RoofRecommendations(property_instance=property_instance13, materials=materials)

        assert not roof_recommender13.recommendations

        roof_recommender13.recommend(phase=0)

        assert len(roof_recommender13.recommendations) == 1

        assert roof_recommender13.recommendations[0]["parts"][0]["depth"] == 150

        assert roof_recommender13.recommendations[0]["total"] == 7800
        assert roof_recommender13.recommendations[0]["new_u_value"] == 0.14
        assert roof_recommender13.recommendations[0]["starting_u_value"] == 2.3

        assert roof_recommender13.recommendations[0]["description"] == \
               "Insulate the home's flat roof with 150mm of Ecotherm Eco-Versal General Purpose Insulation Board"

    def test_property_above(self):
        epc_record = EPCRecord()
        epc_record.prepared_epc = {"county": "Suffolk"}
        property_instance14 = Property(id=0, address="fake", postcode="fake", epc_record=epc_record)
        property_instance14.age_band = "F"
        property_instance14.insulation_floor_area = 100
        property_instance14.roof = {
            'original_description': '(other premises above)',
            'clean_description': '(other premises above)', 'thermal_transmittance': 0,
            'thermal_transmittance_unit': 'w/m-¦k', 'is_pitched': False, 'is_roof_room': False,
            'is_loft': False, 'is_flat': False, 'is_thatched': False, 'is_at_rafters': False,
            'is_assumed': False, 'has_dwelling_above': True, 'is_valid': True,
            'insulation_thickness': None
        }

        roof_recommender14 = RoofRecommendations(property_instance=property_instance14, materials=materials)

        assert not roof_recommender14.recommendations

        roof_recommender14.recommend(phase=0)

        assert not roof_recommender14.recommendations
