from fastapi import status
from fastapi.responses import JSONResponse

from ApiServices.api_handlers import AlchemyJsonResponse
from api_validations.validations_request import (
    InsertDuties,
    UpdateDuties,
    SelectDuties,
    PatchRecord,
    ListOptions,
)

from databases import Departments, Duty, Duties

from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from api_objects.auth.token_objects import EmployeeTokenObject


class DutiesListEventMethods(MethodToEvent):

    event_type = "SELECT"
    __event_keys__ = {
        "44b72beb-53a8-407b-a12a-76e74b65794d": "duties_list",
    }
    __event_validation__ = {"44b72beb-53a8-407b-a12a-76e74b65794d": None}

    @classmethod
    def duties_list(
        cls,
        list_options: ListOptions,
        token_dict: EmployeeTokenObject,
    ):
        Duties.filter_attr = list_options
        records = Duties.filter_all(
            Duties.company_id == token_dict.selected_company.company_id,
        )
        return AlchemyJsonResponse(
            completed=True,
            result=records,
            message="List of Duties records",
        )


class DutiesGetByUUIDEventMethods(MethodToEvent):

    event_type = "GET"
    __event_keys__ = {
        "30c54cce-3303-4d36-959a-b64e383ae177": "duties_get_by_uuid",
    }
    __event_validation__ = {"30c54cce-3303-4d36-959a-b64e383ae177": SelectDuties}

    @classmethod
    def duties_get_by_uuid(
        cls,
        data: SelectDuties,
        token_dict: EmployeeTokenObject,
    ):

        duty = Duty.filter_one(Duty.uu_id == data.duty_uu_id).data
        if not duty:
            return JSONResponse(
                content={
                    "completed": False,
                    "message": "Duty record is not found",
                    "data": {},
                },
                status_code=status.HTTP_404_NOT_FOUND,
            )

        records = Duties.filter_all(
            Duties.duties_id == duty.id,
            Duties.company_id == token_dict.selected_company.company_id,
        )
        if not records.data:
            return JSONResponse(
                content={
                    "completed": False,
                    "message": "Duties record is not found",
                    "data": {},
                },
                status_code=status.HTTP_404_NOT_FOUND,
            )
        return {
            "completed": True,
            "status": "success",
            "data": [record.get_dict() for record in records.data],
        }


class DutiesCreateEventMethods(MethodToEvent):

    event_type = "CREATE"
    __event_keys__ = {
        "3524ae42-0825-4af7-be85-7c890a4f65d3": "duties_create",
    }
    __event_validation__ = {"3524ae42-0825-4af7-be85-7c890a4f65d3": InsertDuties}

    @classmethod
    def duties_create(
        cls,
        data: InsertDuties,
        token_dict: EmployeeTokenObject,
    ):
        duty = Duty.filter_one(Duty.uu_id == data.duties_uu_id).data
        department = Departments.filter_one(Duty.uu_id == data.department_uu_id).data

        created_duties = Duties.find_or_create(
            company_id=token_dict.selected_company.company_id,
            company_uu_id=token_dict.selected_company.company_uu_id,
            duties_id=duty.id,
            duties_uu_id=str(duty.uu_id),
            department_id=department.id,
            department_uu_id=str(department.uu_id),
            is_confirmed=data.is_confirmed,
        )
        if data.is_default_duty:
            created_duties.update(users_default_duty=created_duties.id)

        if not created_duties:
            Duty.save()
            return JSONResponse(
                content={
                    "completed": False,
                    "message": "Failed to create Duties record",
                    "data": {},
                },
                status_code=status.HTTP_400_BAD_REQUEST,
            )
        return {
            "completed": created_duties.is_found,
            "message": (
                "Create Duties record"
                if created_duties.is_found
                else "This record is already created"
            ),
            "data": created_duties.get_dict(),
        }


class DutiesUpdateEventMethods(MethodToEvent):

    event_type = "UPDATE"
    __event_keys__ = {
        "3fc77829-f1ee-4511-a2ca-582daa03125b": "duties_update",
    }
    __event_validation__ = {"3fc77829-f1ee-4511-a2ca-582daa03125b": UpdateDuties}

    @classmethod
    def duties_update(
        cls,
        duties_uu_id: str,
        data: UpdateDuties,
        token_dict: EmployeeTokenObject,
    ):
        find_one_duties = Duties.find_one_or_abort(uu_id=duties_uu_id)
        access_authorized_duties = Duties.select_action(
            duty_id=getattr(token_dict, "duty_id", 5),
            filter_expr=[Duties.id == find_one_duties.id],
        )
        if access_authorized_duties.count:
            data_dict = data.excluded_dump()
            updated_duties = find_one_duties.update(**data_dict)
            Duties.save()
            return {
                "completed": True,
                "message": "Update Duties record",
                "data": updated_duties,
            }
        return {
            "completed": False,
            "message": "Update Duties record failed",
            "data": {},
        }


class DutiesPatchEventMethods(MethodToEvent):

    event_type = "PATCH"
    __event_keys__ = {
        "ca81c6d1-975a-4288-a27b-1069aea84afe": "duties_patch",
    }
    __event_validation__ = {"ca81c6d1-975a-4288-a27b-1069aea84afe": None}

    @classmethod
    def duties_patch(
        cls,
        duties_uu_id: str,
        data: PatchRecord,
        token_dict: EmployeeTokenObject,
    ):
        find_one_duties = Duties.find_one_or_abort(uu_id=duties_uu_id)
        access_authorized_duties = Duties.select_action(
            duty_id=getattr(token_dict, "duty_id", 5),
            filter_expr=[Duties.id == find_one_duties.id],
        )
        if access_authorized_duties.count:
            action = data.excluded_dump()
            find_one_duties.active = bool(action.get("active", find_one_duties.active))
            find_one_duties.is_confirmed = bool(
                action.get("confirm", find_one_duties.is_confirmed)
            )
            find_one_duties.deleted = bool(
                action.get("delete", find_one_duties.deleted)
            )
            find_one_duties.save()
            return {
                "completed": True,
                "message": "Patch Duties record completed",
                "data": find_one_duties.get_dict(),
            }
        return {
            "completed": False,
            "message": "Patch Duties record failed",
            "data": {},
        }


DutiesListEventMethod = DutiesListEventMethods(
    action=ActionsSchema(endpoint="/duties/list")
)
DutiesGetByUUIDEventMethod = DutiesGetByUUIDEventMethods(
    action=ActionsSchema(endpoint="/duties/get_by_duty_uuid")
)
DutiesCreateEventMethod = DutiesCreateEventMethods(
    action=ActionsSchema(endpoint="/duties/create")
)
DutiesUpdateEventMethod = DutiesUpdateEventMethods(
    action=ActionsSchema(endpoint="/duties/update")
)
DutiesPatchEventMethod = DutiesPatchEventMethods(
    action=ActionsSchema(endpoint="/duties/patch")
)
