from typing import Union

from api_validations.validations_response import BuildPartsListResponse
from databases import (
    BuildParts,
)
from api_events.events.abstract_class import MethodToEvent
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
from ApiServices.api_handlers import AlchemyJsonResponse

from api_validations.validations_request import (
    ListOptions,
)
from databases.sql_models.building.decision_book import BuildDecisionBookPayments


class DecisionBookPaymentListEventMethods(MethodToEvent):

    event_type = "SELECT"
    __event_keys__ = {
        "49bb8ab8-520d-4676-a159-aaf84f37f372": "decision_book_payment_list"
    }
    __event_validation__ = {"49bb8ab8-520d-4676-a159-aaf84f37f372": None}

    @classmethod
    def decision_book_payment_list(
        cls,
        list_options: ListOptions,
        token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
    ):
        """
        SELECT payment_plan_time_periods, process_date, payment_amount, currency, payment_types_id,
        payment_types_uu_id, period_time, process_date_y, process_date_m, build_decision_book_item_id,
        build_decision_book_item_uu_id, decision_book_project_id, decision_book_project_uu_id, build_parts_id,
         build_parts_uu_id, id, uu_id, ref_id, created_at, updated_at, cryp_uu_id, created_by, created_by_id,
         updated_by, updated_by_id, confirmed_by, confirmed_by_id, is_confirmed, replication_id, deleted,
          active, is_notification_send, is_email_send, expiry_starts, expiry_ends, account_records_id,
          account_records_uu_id FROM public.build_decision_book_payments;
        """
        from sqlalchemy import func, select, union_all, extract, Integer

        build_parts_id, build_decision_book_id = 7, ""
        payment_types_id_recv, payment_types_id_deb = 46, 45

        BuildDecisionBookPayments.filter_attr = list_options
        # Define the subqueries
        debit_subquery = (
            select(
                BuildDecisionBookPayments.payment_plan_time_periods,
                func.sum(BuildDecisionBookPayments.payment_amount).label("debit"),
                func.cast(0, Integer).label("recv"),
                func.max(BuildDecisionBookPayments.process_date).label("ls"),
            )
            .where(
                BuildDecisionBookPayments.build_parts_id == build_parts_id,
                BuildDecisionBookPayments.payment_types_id == payment_types_id_deb,
                BuildDecisionBookPayments.build_decision_book_id
                == build_decision_book_id,
                extract("year", func.current_date())
                == extract("year", BuildDecisionBookPayments.process_date),
                extract("month", func.current_date())
                == extract("month", BuildDecisionBookPayments.process_date),
            )
            .group_by(BuildDecisionBookPayments.payment_plan_time_periods)
        )

        recv_subquery = (
            select(
                BuildDecisionBookPayments.payment_plan_time_periods,
                func.cast(0, Integer).label("debit"),
                func.sum(BuildDecisionBookPayments.payment_amount).label("recv"),
                func.max(BuildDecisionBookPayments.process_date).label("ls"),
            )
            .where(
                BuildDecisionBookPayments.build_parts_id == build_parts_id,
                BuildDecisionBookPayments.payment_types_id == payment_types_id_recv,
                BuildDecisionBookPayments.build_decision_book_id
                == build_decision_book_id,
                extract("year", func.current_date())
                == extract("year", BuildDecisionBookPayments.process_date),
                extract("month", func.current_date())
                == extract("month", BuildDecisionBookPayments.process_date),
            )
            .group_by(BuildDecisionBookPayments.payment_plan_time_periods)
        )

        # Combine the subqueries using union_all
        combined_subquery = union_all(debit_subquery, recv_subquery).alias("AA")

        # Final query
        final_query = select(
            combined_subquery.c.payment_plan_time_periods,
            func.sum(combined_subquery.c.debit).label("debit"),
            func.sum(combined_subquery.c.recv).label("recv"),
            combined_subquery.c.ls.label("Last Seen"),
        ).group_by(
            combined_subquery.c.payment_plan_time_periods, combined_subquery.c.ls
        )

        # Execute the query
        book_payments_month = BuildDecisionBookPayments.session.execute(
            final_query
        ).fetchall()
        print("book_payments_month", book_payments_month)

        debit_subquery = (
            select(
                BuildDecisionBookPayments.payment_plan_time_periods,
                func.sum(BuildDecisionBookPayments.payment_amount).label("debit"),
                func.cast(0, Integer).label("recv"),
                func.max(BuildDecisionBookPayments.process_date).label("ls"),
            )
            .where(
                BuildDecisionBookPayments.build_parts_id == build_parts_id,
                BuildDecisionBookPayments.payment_types_id == payment_types_id_deb,
                BuildDecisionBookPayments.build_decision_book_id
                == build_decision_book_id,
            )
            .group_by(BuildDecisionBookPayments.payment_plan_time_periods)
        )

        recv_subquery = (
            select(
                BuildDecisionBookPayments.payment_plan_time_periods,
                func.cast(0, Integer).label("debit"),
                func.sum(BuildDecisionBookPayments.payment_amount).label("recv"),
                func.max(BuildDecisionBookPayments.process_date).label("ls"),
            )
            .where(
                BuildDecisionBookPayments.build_parts_id == build_parts_id,
                BuildDecisionBookPayments.payment_types_id == payment_types_id_recv,
                BuildDecisionBookPayments.build_decision_book_id
                == build_decision_book_id,
            )
            .group_by(BuildDecisionBookPayments.payment_plan_time_periods)
        )

        # Combine the subqueries using union_all
        combined_subquery = union_all(debit_subquery, recv_subquery).alias("AA")

        # Final query
        final_query = select(
            combined_subquery.c.payment_plan_time_periods,
            func.sum(combined_subquery.c.debit).label("debit"),
            func.sum(combined_subquery.c.recv).label("recv"),
            combined_subquery.c.ls.label("Last Seen"),
        ).group_by(
            combined_subquery.c.payment_plan_time_periods, combined_subquery.c.ls
        )

        # Execute the query
        book_payments = BuildDecisionBookPayments.session.execute(
            final_query
        ).fetchall()
        print("book_payments", book_payments)
        return AlchemyJsonResponse(
            completed=True,
            message="Building Parts Records are listed",
            result=[book_payments, book_payments_month],
            cls_object=BuildParts,
            response_model=BuildPartsListResponse,
            filter_attributes=list_options,
        )
