import typing

from databases import (
    Build,
    BuildArea,
)

from api_validations.validations_request import (
    InsertBuildArea,
    UpdateBuildArea,
    ListOptions,
)

from api_validations.core_response import AlchemyJsonResponse
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject


class BuildAreaListEventMethods(MethodToEvent):

    event_type = "SELECT"
    __event_keys__ = {
        "0bb51845-65a2-4340-8872-a3b5aad95468": "build_area_list",
    }

    @classmethod
    def build_area_list(
        cls,
        list_options: ListOptions,
        token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
    ):
        if isinstance(token_dict, OccupantTokenObject):
            build_ids = Build.filter_all(
                Build.id == token_dict.selected_occupant.build_id,
            ).data
            BuildArea.pre_query = BuildArea.filter_all(
                BuildArea.build_id.in_([build.id for build in build_ids]),
            ).query
        elif isinstance(token_dict, EmployeeTokenObject):
            build_ids = Build.select_action(
                employee_id=token_dict.selected_company.employee_id
            )
            BuildArea.pre_query = BuildArea.filter_all(
                BuildArea.build_id.in_([build.id for build in build_ids]),
            ).query
        BuildArea.filter_attr = list_options
        records = BuildArea.filter_all()
        return AlchemyJsonResponse(
            completed=True, message="List of Build Area", result=records
        )


class BuildAreaCreateEventMethods(MethodToEvent):

    event_type = "CREATE"
    __event_keys__ = {
        "a10571fa-ac1d-4546-9272-cacb911d8004": "build_area_create",
    }

    @classmethod
    def build_area_create(
        cls,
        data: InsertBuildArea,
        token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
    ):
        data_dict = data.excluded_dump()
        selected_build = None
        if isinstance(token_dict, OccupantTokenObject):
            if not token_dict.selected_occupant.build_uuid == data.build_uu_id:
                BuildArea.raise_http_exception(
                    status_code="HTTP_403_FORBIDDEN",
                    error_case="UNAUTHORIZED",
                    message=f"Occupant can not create build area for {data.build_uu_id}",
                    data={
                        "build_uu_id": data.build_uu_id,
                    },
                )
            selected_build = Build.filter_by_one(
                system=True, uu_id=data.build_uu_id
            ).data
        elif isinstance(token_dict, EmployeeTokenObject):
            build_ids = Build.select_action(
                employee_id=token_dict.selected_company.employee_id
            ).all()
            if not str(data.build_uu_id) in [str(build.uu_id) for build in build_ids]:
                BuildArea.raise_http_exception(
                    status_code="HTTP_403_FORBIDDEN",
                    error_case="UNAUTHORIZED",
                    message=f"Employee can not create build area for {data.build_uu_id}",
                    data={
                        "build_uu_id": data.build_uu_id,
                    },
                )
            selected_build = Build.filter_by_one(
                system=True, uu_id=data.build_uu_id
            ).data

        data_dict["build_id"] = selected_build.id
        data_dict["build_uu_id"] = str(selected_build.uu_id)
        created_build_part = BuildArea.find_or_create(**data_dict)
        created_build_part.save()
        created_build_part.update(is_confirmed=True)
        created_build_part.save()
        return AlchemyJsonResponse(
            completed=True,
            message="Created Build Area",
            result=created_build_part.get_dict(),
        )


class BuildAreaUpdateEventMethods(MethodToEvent):

    event_type = "UPDATE"
    __event_keys__ = {
        "58178738-7489-4f8f-954e-5c8f083c1845": "build_area_update",
    }

    @classmethod
    def build_area_update(
        cls,
        build_uu_id: str,
        data: UpdateBuildArea,
        token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
    ):
        return AlchemyJsonResponse(
            completed=False,
            message="Update Build record",
            result=None,
        )


class BuildAreaPatchEventMethods(MethodToEvent):

    event_type = "PATCH"
    __event_keys__ = {
        "d6bd8a5f-fa76-49da-b82e-4a95f1bcce39": "build_area_patch",
    }

    @classmethod
    def build_area_patch(
        cls,
        build_uu_id: str,
        data,
        token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
    ):
        return AlchemyJsonResponse(
            completed=False,
            message="Patch Build record",
            result=None,
        )


BuildAreaListEventMethod = BuildAreaListEventMethods(
    action=ActionsSchema(endpoint="/building/area/list")
)
BuildAreaCreateEventMethod = BuildAreaCreateEventMethods(
    action=ActionsSchema(endpoint="/building/area/create")
)
BuildAreaUpdateEventMethod = BuildAreaUpdateEventMethods(
    action=ActionsSchema(endpoint="/building/area/update")
)
BuildAreaPatchEventMethod = BuildAreaPatchEventMethods(
    action=ActionsSchema(endpoint="/building/area/patch")
)
