from typing import Union

from fastapi.exceptions import HTTPException

from databases import (
    Events,
    Employees,
    Staff,
    Duties,
    Event2Occupant,
    Event2Employee,
    BuildLivingSpace,
)
from api_validations.validations_request import (
    RegisterEvents2Employee,
    RegisterEvents2Occupant,
    ListOptions,
)

from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from ApiServices.api_handlers import AlchemyJsonResponse


class EventsListEventMethods(MethodToEvent):

    event_type = "SELECT"
    __event_keys__ = {
        "9fa01bef-c0e8-4fe1-b9ed-2ff1c4f35faa": "events_list",
    }
    __event_validation__ = {"9fa01bef-c0e8-4fe1-b9ed-2ff1c4f35faa": None}

    @classmethod
    def events_list(
        cls,
        list_options: ListOptions,
        token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
    ):
        list_options.page = 1
        list_options.size = 10000
        Events.filter_attr = list_options
        if isinstance(token_dict, OccupantTokenObject):
            occupant_events = Event2Occupant.filter_all(
                Event2Occupant.build_living_space_id
                == token_dict.selected_occupant.living_space_id
            ).data
            records = Events.filter_all(
                Events.id.in_([event.event_id for event in occupant_events])
            )
            return AlchemyJsonResponse(
                completed=True,
                message="Events are listed successfully",
                result=records,
            )
        elif isinstance(token_dict, EmployeeTokenObject):
            employee_events = Event2Employee.filter_all(
                Event2Employee.employee_id == token_dict.selected_company.employee_id
            ).data
            records = Events.filter_all(
                Events.id.in_([event.event_id for event in employee_events])
            )
            return AlchemyJsonResponse(
                completed=True,
                message="Events are listed successfully",
                result=records,
            )
        return AlchemyJsonResponse(
            completed=False,
            message="Events are NOT listed successfully",
            result=[],
        )


class EventsBindEventToOccupantMethods(MethodToEvent):

    event_type = "UPDATE"
    __event_keys__ = {
        "d9aa58aa-37f7-4c27-861d-3105f76f5cdc": "bind_events_employee",
    }
    __event_validation__ = {
        "d9aa58aa-37f7-4c27-861d-3105f76f5cdc": RegisterEvents2Employee
    }

    @classmethod
    def bind_events_employee(cls, data: RegisterEvents2Employee, token_dict):
        events = Events.filter_all(
            Events.uu_id.in_(data.event_id),
        ).data
        if not events:
            raise HTTPException(
                status_code=401,
                detail="No event found. Please contact your super user.",
            )
        employee_is_not_valid = False
        employee = Employees.filter_one(
            Employees.employee_uu_id == data.employee_uu_id,
        ).data
        if employee:
            staff = Staff.filter_one(
                Staff.id == employee.staff_id,
            ).data
            duties = Duties.filter_one(
                Duties.id == staff.duties_id,
            ).data
            if duties.company_id not in token_dict.companies_id_list:
                employee_is_not_valid = True

        if employee_is_not_valid:
            raise HTTPException(
                status_code=401,
                detail="This employee can not be reached by this user. Please contact your super user.",
            )

        for event in events:
            employee = Event2Employee.find_or_create(
                **token_dict.user_creds, employee_id=employee.id, event_id=event.id
            )
        Events.save()
        return {
            "status": "success",
            "message": "Events registered successfully.",
            "events": [event.uu_id for event in events.data],
        }


class EventsBindEventToEmployeeMethods(MethodToEvent):

    event_type = "UPDATE"
    __event_keys__ = {
        "8bb4f4fc-b474-427e-90b3-d8681f308bb5": "bind_events_occupant",
    }
    __event_validation__ = {
        "8bb4f4fc-b474-427e-90b3-d8681f308bb5": RegisterEvents2Occupant
    }

    @classmethod
    def bind_events_occupant(cls, data: RegisterEvents2Occupant, token_dict):
        events = Events.filter_all(
            Events.uu_id.in_(data.event_id),
        ).data
        if not events:
            raise HTTPException(
                status_code=401,
                detail="No event found. Please contact your super user.",
            )
        occupant = BuildLivingSpace.filter_one(
            BuildLivingSpace.uu_id == data.build_living_space_uu_id,
        ).data
        if not occupant:
            raise HTTPException(
                status_code=401,
                detail="This occupant can not be reached by this user. Please contact your super user.",
            )
        for event in events:
            occupant = Event2Occupant.find_or_create(
                **token_dict.user_creds,
                build_living_space_id=occupant.id,
                event_id=event.id,
            )
        Events.save()
        return {
            "status": "success",
            "message": "Events registered successfully.",
            "events": [event.uu_id for event in events.data],
        }


EventsBindEventToOccupantMethod = EventsBindEventToOccupantMethods(
    action=ActionsSchema(endpoint="/bind/events/occupant")
)
EventsBindEventToEmployeeMethod = EventsBindEventToEmployeeMethods(
    action=ActionsSchema(endpoint="/bind/events/employee")
)
EventsListEventMethod = EventsListEventMethods(
    action=ActionsSchema(endpoint="/event/list")
)

# EventsCreateEventMethod = EventsCreateEventMethods(
#     action=ActionsSchema(endpoint="/event/create")
# )
# EventsUpdateEventMethod = EventsUpdateEventMethods(
#     action=ActionsSchema(endpoint="/event/update")
# )
# EventsPatchEventMethod = EventsPatchEventMethods(
#     action=ActionsSchema(endpoint="/event/patch")
# )
#

# class EventsCreateEventMethods(MethodToEvent):
#
#     event_type = "CREATE"
#     __event_keys__ = {
#         "514a9f8f-e5e5-4e10-9d0b-2de8f461fc1b": "events_create",
#     }
#
#     @classmethod
#     def events_create(cls, data: CreateEvents, token_dict):
#         event = Events.find_or_create(
#             **token_dict.user_creds,
#             event_name=data.event_name,
#             event_description=data.event_description,
#             event_date=data.event_date,
#             event_location=data.event_location,
#             active=True,
#             deleted=False,
#         )
#         Events.save()
#         return {
#             "status": "success",
#             "message": "Event created successfully.",
#             "event": event.uu_id,
#         }
# class EventsUpdateEventMethods(MethodToEvent):
#
#     event_type = "UPDATE"
#     __event_keys__ = {
#         "f94e7b79-2369-4840-bf2b-244934ca3136": "events_update",
#     }
#
#     @classmethod
#     def events_update(cls, data: CreateEvents, token_dict):
#         event = Events.filter_by_one(uu_id=data.uu_id, **Events.valid_record_dict).data
#         if not event:
#             raise HTTPException(
#                 status_code=404,
#                 detail="No event found. Please contact your responsible company.",
#             )
#         event.update(
#             **token_dict.user_creds,
#             event_name=data.event_name,
#             event_description=data.event_description,
#             event_date=data.event_date,
#             event_location=data.event_location,
#         )
#         Events.save()
#         return {
#             "status": "success",
#             "message": "Event updated successfully.",
#             "event": event.uu_id,
#         }
#
#
# class EventsPatchEventMethods(MethodToEvent):
#
#     event_type = "PATCH"
#     __event_keys__ = {
#         "41944c63-22d3-4866-affd-34bcd49da58b": "events_patch",
#     }
#
#     @classmethod
#     def events_patch(cls, data: CreateEvents, token_dict):
#         event = Events.filter_by_one(uu_id=data.uu_id, **Events.valid_record_dict).data
#         if not event:
#             raise HTTPException(
#                 status_code=404,
#                 detail="No event found. Please contact your responsible company.",
#             )
#         event.update(
#             **token_dict.user_creds,
#             event_name=data.event_name,
#             event_description=data.event_description,
#             event_date=data.event_date,
#             event_location=data.event_location,
#         )
#         return {
#             "status": "success",
#             "message": "Event patched successfully.",
#             "event": event.uu_id,
#         }
