from typing import List

import inject

from core.domains.plant.dto.plant_dto import GetPlantMainDto, GetPlantDetailDto
from core.domains.plant.entity.plant_entity import PlantCategoryEntity, PlantProfileEntity, MainPlantInfoEntity, \
    WeeklyPlantEntity
from core.domains.plant.enum.plant_enum import TemperatureApprValueEnum, IndoorHumidityApprValueEnum, \
    SoilHumidityApprValueEnum, TemperatureApprWordEnum, IndoorHumidityApprWordEnum, SoilHumidityApprWordEnum, \
    IlluminanceApprWordEnum, IlluminanceApprValueEnum, TemperatureApprEventEnum, IndoorHumidityApprEventEnum, \
    SoilHumidityApprEventEnum, IlluminanceApprEventEnum
from core.domains.plant.repository.plant_repository import PlantRepository
from core.use_case_output import UseCaseSuccessOutput, UseCaseFailureOutput


class PlantBaseUseCase:
    @inject.autoparams()
    def __init__(self, plant_repo: PlantRepository):
        self._plant_repo = plant_repo


class GetPlantCategoryUseCase(PlantBaseUseCase):
    def execute(self) -> UseCaseSuccessOutput | UseCaseFailureOutput:
        results: List[PlantCategoryEntity] = self._plant_repo.get_plant_categories()
        return UseCaseSuccessOutput(value=results)


class GetPlantMainUseCase(PlantBaseUseCase):
    def execute(self, dto: GetPlantMainDto) -> UseCaseSuccessOutput | UseCaseFailureOutput:
        plant_profile: PlantProfileEntity = self._plant_repo.get_plant_infos(user_id=dto.user_id)
        plant_info: MainPlantInfoEntity | None = self._get_plant_status(plant_profile=plant_profile, div=dto.div)

        return UseCaseSuccessOutput(value=dict(plant_profile=plant_profile, plant_info=plant_info))

    def _get_plant_status(self, plant_profile: PlantProfileEntity, div: str) -> MainPlantInfoEntity | None:
        if plant_profile.plant_infos:
            plant_info = plant_profile.plant_infos[0]
            div_data, plant_status_1, plant_status_2 = None, None, None
            match div:
                case "temperature":
                    div_data = plant_info.temperature
                    if TemperatureApprValueEnum.HIGH.value <= div_data:  # high
                        plant_status_1 = TemperatureApprWordEnum.HIGH.value
                        plant_status_2 = TemperatureApprEventEnum.HIGH.value
                    elif TemperatureApprValueEnum.LOW.value >= div_data:  # low
                        plant_status_1 = TemperatureApprWordEnum.LOW.value
                        plant_status_2 = TemperatureApprEventEnum.LOW.value
                    else:  # 적정수치
                        plant_status_1 = TemperatureApprWordEnum.APPR.value
                        plant_status_2 = TemperatureApprEventEnum.APPR.value

                case "indoor_humidity":
                    div_data = plant_info.indoor_humidity
                    if IndoorHumidityApprValueEnum.HIGH.value <= div_data:  # high
                        plant_status_1 = IndoorHumidityApprWordEnum.HIGH.value
                        plant_status_2 = IndoorHumidityApprEventEnum.HIGH.value
                    elif IndoorHumidityApprValueEnum.LOW.value >= div_data:  # low
                        plant_status_1 = IndoorHumidityApprWordEnum.LOW.value
                        plant_status_2 = IndoorHumidityApprEventEnum.LOW.value
                    else:  # 적정수치
                        plant_status_1 = IndoorHumidityApprWordEnum.APPR.value
                        plant_status_2 = IndoorHumidityApprEventEnum.APPR.value

                case "soil_humidity":
                    div_data = plant_info.soil_humidity
                    if SoilHumidityApprValueEnum.HIGH.value <= div_data:  # high
                        plant_status_1 = SoilHumidityApprWordEnum.HIGH.value
                        plant_status_2 = SoilHumidityApprEventEnum.HIGH.value
                    elif SoilHumidityApprValueEnum.LOW.value >= div_data:  # low
                        plant_status_1 = SoilHumidityApprWordEnum.LOW.value
                        plant_status_2 = SoilHumidityApprEventEnum.LOW.value
                    else:  # 적정수치
                        plant_status_1 = SoilHumidityApprWordEnum.APPR.value
                        plant_status_2 = SoilHumidityApprEventEnum.APPR.value

                case "illuminance":
                    div_data = plant_info.illuminance
                    if IlluminanceApprValueEnum.HIGH.value <= div_data:  # high
                        plant_status_1 = IlluminanceApprWordEnum.HIGH.value
                        plant_status_2 = IlluminanceApprEventEnum.HIGH.value
                    elif IlluminanceApprValueEnum.LOW.value >= div_data:  # low
                        plant_status_1 = IlluminanceApprWordEnum.LOW.value
                        plant_status_2 = IlluminanceApprEventEnum.LOW.value
                    else:  # 적정수치
                        plant_status_1 = IlluminanceApprWordEnum.APPR.value
                        plant_status_2 = IlluminanceApprEventEnum.APPR.value
                case _:  # default
                    pass

            return MainPlantInfoEntity(
                div=div,
                div_data=div_data,
                plant_status_1=plant_status_1,
                plant_status_2=f"{plant_profile.name}{plant_status_2}"
            )

        return None


class GetPlantDetailUseCase(PlantBaseUseCase):
    def execute(self, dto: GetPlantDetailDto) -> UseCaseSuccessOutput | UseCaseFailureOutput:
        plant_profile: PlantProfileEntity = self._plant_repo.get_plant_infos(user_id=dto.user_id)
        weekly_plant_info: List[WeeklyPlantEntity | None] = self._plant_repo.get_weekly_plant_infos(plant_id=plant_profile.id, div=dto.div)
        monthly_plant_info: List[WeeklyPlantEntity | None] = self._plant_repo.get_monthly_plant_infos(plant_id=plant_profile.id, div=dto.div)

        plant_info: MainPlantInfoEntity | None = self._get_plant_status(plant_profile=plant_profile, div=dto.div)

        return UseCaseSuccessOutput(value=dict(plant_profile=plant_profile, plant_info=plant_info, weekly_plant_info=weekly_plant_info, monthly_plant_info=monthly_plant_info))

    def _get_plant_status(self, plant_profile: PlantProfileEntity, div: str) -> MainPlantInfoEntity | None:
        if plant_profile.plant_infos:
            plant_info = plant_profile.plant_infos[0]
            div_data, plant_status_1, plant_status_2 = None, None, None
            match div:
                case "temperature":
                    div_data = plant_info.temperature
                    if TemperatureApprValueEnum.HIGH.value <= div_data:  # high
                        plant_status_1 = TemperatureApprWordEnum.HIGH.value
                        plant_status_2 = TemperatureApprEventEnum.HIGH.value
                    elif TemperatureApprValueEnum.LOW.value >= div_data:  # low
                        plant_status_1 = TemperatureApprWordEnum.LOW.value
                        plant_status_2 = TemperatureApprEventEnum.LOW.value
                    else:  # 적정수치
                        plant_status_1 = TemperatureApprWordEnum.APPR.value
                        plant_status_2 = TemperatureApprEventEnum.APPR.value

                case "indoor_humidity":
                    div_data = plant_info.indoor_humidity
                    if IndoorHumidityApprValueEnum.HIGH.value <= div_data:  # high
                        plant_status_1 = IndoorHumidityApprWordEnum.HIGH.value
                        plant_status_2 = IndoorHumidityApprEventEnum.HIGH.value
                    elif IndoorHumidityApprValueEnum.LOW.value >= div_data:  # low
                        plant_status_1 = IndoorHumidityApprWordEnum.LOW.value
                        plant_status_2 = IndoorHumidityApprEventEnum.LOW.value
                    else:  # 적정수치
                        plant_status_1 = IndoorHumidityApprWordEnum.APPR.value
                        plant_status_2 = IndoorHumidityApprEventEnum.APPR.value

                case "soil_humidity":
                    div_data = plant_info.soil_humidity
                    if SoilHumidityApprValueEnum.HIGH.value <= div_data:  # high
                        plant_status_1 = SoilHumidityApprWordEnum.HIGH.value
                        plant_status_2 = SoilHumidityApprEventEnum.HIGH.value
                    elif SoilHumidityApprValueEnum.LOW.value >= div_data:  # low
                        plant_status_1 = SoilHumidityApprWordEnum.LOW.value
                        plant_status_2 = SoilHumidityApprEventEnum.LOW.value
                    else:  # 적정수치
                        plant_status_1 = SoilHumidityApprWordEnum.APPR.value
                        plant_status_2 = SoilHumidityApprEventEnum.APPR.value

                case "illuminance":
                    div_data = plant_info.illuminance
                    if IlluminanceApprValueEnum.HIGH.value <= div_data:  # high
                        plant_status_1 = IlluminanceApprWordEnum.HIGH.value
                        plant_status_2 = IlluminanceApprEventEnum.HIGH.value
                    elif IlluminanceApprValueEnum.LOW.value >= div_data:  # low
                        plant_status_1 = IlluminanceApprWordEnum.LOW.value
                        plant_status_2 = IlluminanceApprEventEnum.LOW.value
                    else:  # 적정수치
                        plant_status_1 = IlluminanceApprWordEnum.APPR.value
                        plant_status_2 = IlluminanceApprEventEnum.APPR.value
                case _:  # default
                    pass

            return MainPlantInfoEntity(
                div=div,
                div_data=div_data,
                plant_status_1=plant_status_1,
                plant_status_2=f"{plant_profile.name}{plant_status_2}"
            )

        return None