import pytest
from etl.epc_clean.tests.test_data.test_roof_attributes_cases import clean_roof_test_cases
from etl.epc_clean.epc_attributes.RoofAttributes import RoofAttributes


# For local testing
# from pathlib import Path
# if __file__ == "<input>":
#     input_data_path = Path("./model_data/tests/test_data/EpcClean_inputs.obj")
# else:
#     current_file_path = Path(__file__)
#     input_data_path = current_file_path.parent / 'test_data' / 'EpcClean_inputs.obj'


class TestRoofAttributes:

    def test_init(self):
        # Test initialization with a valid description
        valid_description = "(Another dwelling above)"
        floor_attr = RoofAttributes(valid_description)
        assert floor_attr.description == valid_description.lower()

        with pytest.raises(ValueError):
            RoofAttributes('description without keywords')

    def test_empty_str(self):
        # Test initialization with an empty description
        assert RoofAttributes('').process() == {
            'thermal_transmittance': None, 'thermal_transmittance_unit': None, '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': False, 'is_valid': False, 'insulation_thickness': None
        }

    def test_clean_roof(self):
        result = RoofAttributes('Pitched, 270 mm loft insulation').process()

        # change the expected output based on your requirement
        expected_output = {
            "is_valid": True,
            "is_at_rafters": False,
            "is_pitched": True,
            "is_roof_room": False,
            "is_loft": True,
            "insulation_thickness": "270",
            "has_dwelling_above": False,
            "is_assumed": False,
            "is_flat": False,
            "is_thatched": False,
            "thermal_transmittance": None,
            "thermal_transmittance_unit": None
        }

        for k in expected_output:
            assert result[k] == expected_output[k]

        assert result == expected_output

    @pytest.mark.parametrize(
        "test_case",
        clean_roof_test_cases
    )
    def test_process(self, test_case):
        expected_result = test_case.copy()
        del expected_result["original_description"]
        result = RoofAttributes(test_case['original_description']).process()
        # Ensure the output ordering is correct
        assert sorted(result.items()) == sorted(expected_result.items())

    def test_clean_roof_with_dwelling_above(self):
        result = RoofAttributes('(another dwelling above)').process()

        expected_output = {
            "is_valid": True,
            "is_at_rafters": False,
            "is_pitched": False,
            "is_roof_room": False,
            "is_loft": False,
            "insulation_thickness": None,
            "has_dwelling_above": True,
            "is_assumed": False,
            "is_flat": False,
            "is_thatched": False,
            "thermal_transmittance": 0,
            "thermal_transmittance_unit": "w/m-¦k",
        }

        for k in expected_output:
            assert result[k] == expected_output[k]

    def test_clean_roof_invalid(self):
        with pytest.raises(ValueError):
            RoofAttributes('nonsense string').process()

    def test_clean_roof_edge_cases(self):
        # Insulation thickness edge case
        assert RoofAttributes('Pitched, 99999 mm loft insulation').process()['insulation_thickness'] == "99999"
        assert RoofAttributes('Pitched, 1 mm loft insulation').process()['insulation_thickness'] == "1"

        # Special characters in the description - implement this later
        # result = RoofAttributes('Pitched, **270** mm loft insulation').process()
        # assert result['insulation_thickness'] == 270

    def test_clean_roof_type(self):
        for roof_type in ['pitched', 'roof room', 'loft', 'flat', 'thatched', 'at rafters', 'assumed']:
            result = RoofAttributes(f'{roof_type}, 200 mm insulation').process()
            assert result[f'is_{roof_type.replace(" ", "_")}'] is True

    def test_clean_roof_thermal_transmittance(self):
        result = RoofAttributes('Pitched, 200 mm insulation, average thermal transmittance 0.13 w/m-¦k').process()
        assert result['thermal_transmittance'] == 0.13
        assert result['thermal_transmittance_unit'] == 'w/m-¦k'
