from pydantic import BaseModel, conlist, validator
from typing import Optional


class PlanTriggerRequest(BaseModel):
    budget: Optional[float] = None
    goal: str
    housing_type: str
    goal_value: str
    portfolio_id: int
    trigger_file_path: str
    already_installed_file_path: Optional[str] = None
    patches_file_path: Optional[str] = None
    non_invasive_recommendations_file_path: Optional[str] = None
    exclusions: Optional[conlist(str, min_items=1)] = None

    # Pre-defined list of possibilities for exclusions
    _allowed_exclusions = {
        "wall_insulation",
        "ventilation",
        "roof_insulation",
        "floor_insulation",
        "windows",
        "fireplace",
        "heating",
        "hot_water",
        "lighting",
        "solar_pv"
    }

    _allowed_goals = {"Increase EPC"}

    _allowed_housing_types = {"Social", "Private"}

    # Validator to ensure exclusions are within the pre-defined possibilities
    @validator('exclusions', each_item=True)
    def check_exclusions(cls, v):
        if v not in cls._allowed_exclusions:
            raise ValueError(f"{v} is not an allowed exclusion")
        return v

    # Validator to ensure that the goal is within the pre-defined possibilities
    @validator('goal')
    def check_goal(cls, v):
        if v not in cls._allowed_goals:
            raise ValueError(f"{v} is not a valid goal")
        return v

    # Validator to ensure that the housing type is within the pre-defined possibilities
    @validator('housing_type')
    def check_housing_type(cls, v):
        if v not in cls._allowed_housing_types:
            raise ValueError(f"{v} is not a valid housing type")
        return v


class MdsRequest(PlanTriggerRequest):
    # When creating the mds report, we allow an optional list of measures to select from. If this is passed, it will
    # cause the service to select the optimal package from the list of measures
    measures: Optional[conlist(str, min_items=1)] = None
