import typing

from fastapi import status
from fastapi.responses import JSONResponse

from databases import Companies

from api_validations.validations_request import (
    InsertCompany,
    UpdateCompany,
    ListOptions,
    PatchRecord,
)

from api_validations.validations_response import CompanyListResponse

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 CompanyListEventMethods(MethodToEvent):

    event_type = "SELECT"
    __event_keys__ = {
        "f6900cb5-ac5b-478e-8e7c-fa87e65cd2e5": "company_list",
    }
    __event_validation__ = {"f6900cb5-ac5b-478e-8e7c-fa87e65cd2e5": CompanyListResponse}

    @classmethod
    def company_list(
        cls,
        list_options: ListOptions,
        token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
    ):
        if isinstance(token_dict, EmployeeTokenObject):
            Companies.pre_query = Companies.select_action(
                duty_id_list=[
                    token_dict.selected_company.duty_id,
                    token_dict.selected_company.bulk_duties_id,
                ]
            )
        elif isinstance(token_dict, OccupantTokenObject):
            Companies.pre_query = Companies.filter_all(
                Companies.id == token_dict.selected_occupant.responsible_company_id
            ).query
        Companies.filter_attr = list_options
        records = Companies.filter_all()
        return AlchemyJsonResponse(
            completed=True,
            message="Companies listed successfully",
            result=records,
            cls_object=Companies,
            filter_attributes=list_options,
            response_model=CompanyListResponse,
        )


class CompanyCreateEventMethods(MethodToEvent):

    event_type = "CREATE"
    __event_keys__ = {
        "76f11a08-5f4a-4e1f-961f-aaef21699acd": "company_create",
    }
    __event_validation__ = {"76f11a08-5f4a-4e1f-961f-aaef21699acd": InsertCompany}

    @classmethod
    def company_create(
        cls,
        data: InsertCompany,
        token_dict: EmployeeTokenObject,
    ):
        created_company = Companies.insert_one(data).data
        created_company.update(
            related_company=token_dict.selected_company.company_uu_id
        )
        created_company.save()
        return AlchemyJsonResponse(
            completed=True,
            message="Company created successfully",
            result=created_company.get_dict(),
        )


class CompanyUpdateEventMethods(MethodToEvent):

    event_type = "UPDATE"
    __event_keys__ = {
        "41ea7f29-006a-4310-b5c4-b2a0e1a504bd": "company_update",
    }
    __event_validation__ = {
        "41ea7f29-006a-4310-b5c4-b2a0e1a504bd": UpdateCompany,
    }

    @classmethod
    def company_update(
        cls, company_uu_id: str, data: UpdateCompany, token_dict: EmployeeTokenObject
    ):
        Companies.pre_query = Companies.select_action(
            duty_id_list=[
                token_dict.selected_company.bulk_duties_id,
                token_dict.selected_company.duty_id,
            ],
        )
        company = Companies.update_one(company_uu_id, data).data
        if not company:
            return AlchemyJsonResponse(
                completed=False,
                message="Company not found",
                result={},
                status_code="HTTP_404_NOT_FOUND",
            )
        company.save()
        return AlchemyJsonResponse(
            completed=True,
            message="Company updated successfully",
            result=company.get_dict(),
        )


class CompanyPatchEventMethods(MethodToEvent):

    event_type = "PATCH"
    __event_keys__ = {
        "6320d696-1fd1-49f9-860a-8f22e5b8a68d": "company_patch",
    }
    __event_validation__ = {"6320d696-1fd1-49f9-860a-8f22e5b8a68d": None}

    @classmethod
    def company_patch(
        cls, company_uu_id: str, data: PatchRecord, token_dict: EmployeeTokenObject
    ):
        Companies.pre_query = Companies.select_action(
            duty_id_list=[
                token_dict.selected_company.bulk_duties_id,
                token_dict.selected_company.duty_id,
            ],
        )
        company = Companies.patch_one(company_uu_id, data).data
        if not company:
            return AlchemyJsonResponse(
                completed=False,
                message="Company not found",
                result={},
                status_code="HTTP_404_NOT_FOUND",
            )
        company.save()
        return AlchemyJsonResponse(
            completed=True,
            message="Company patched successfully",
            result=company.get_dict(),
        )


CompanyPatchEventMethod = CompanyListEventMethods(
    action=ActionsSchema(endpoint="/company/list")
)
CompanyCreateEventMethod = CompanyCreateEventMethods(
    action=ActionsSchema(endpoint="/company/create")
)
CompanyUpdateEventMethod = CompanyUpdateEventMethods(
    action=ActionsSchema(endpoint="/company/update")
)
CompanyListEventMethod = CompanyPatchEventMethods(
    action=ActionsSchema(endpoint="/company/patch")
)
