from databases.sql_models.core_mixin import CrudCollection

from sqlalchemy import (
    String,
    ForeignKey,
    Numeric,
    SmallInteger,
    Boolean,
    Integer,
    Index,
)
from sqlalchemy.orm import mapped_column, Mapped


class Events(CrudCollection):
    """
    Events class based on declarative_base and BaseMixin via session
    If Events2Occupants and Events2Employees are not found for user request, response 401 Unauthorized
    """

    __tablename__ = "events"
    __exclude__fields__ = []

    event_type: Mapped[str] = mapped_column(String, nullable=False, comment="default")
    function_code: Mapped[str] = mapped_column(
        String, nullable=False, comment="function code"
    )
    function_class: Mapped[str] = mapped_column(
        String, nullable=False, comment="class name"
    )

    # name: Mapped[str] = mapped_column(String, nullable=True)  # form or page title
    description: Mapped[str] = mapped_column(
        String, server_default=""
    )  # form or page description
    property_description: Mapped[str] = mapped_column(String, server_default="")

    marketing_layer = mapped_column(SmallInteger, server_default="3")
    cost: Mapped[float] = mapped_column(Numeric(20, 2), server_default="0.00")
    unit_price: Mapped[float] = mapped_column(Numeric(20, 2), server_default="0.00")

    endpoint_id: Mapped[int] = mapped_column(
        ForeignKey("endpoint_restriction.id"), nullable=True
    )
    endpoint_uu_id: Mapped[str] = mapped_column(
        String, nullable=True, comment="Endpoint UUID"
    )

    __table_args__ = ({"comment": "Events Information"},)


class Modules(CrudCollection):
    """
    Modules class based on declarative_base and BaseMixin via session
    """

    __tablename__ = "modules"
    __exclude__fields__ = []

    module_name: Mapped[str] = mapped_column(
        String, nullable=False, comment="Module Name"
    )
    module_description: Mapped[str] = mapped_column(String, server_default="")
    module_code: Mapped[str] = mapped_column(
        String, nullable=False, comment="Module Code"
    )
    module_layer = mapped_column(Integer, nullable=False, comment="Module Layer")
    is_default_module = mapped_column(Boolean, server_default="0")

    def retrieve_services(self):
        services = Services.filter_all(Services.module_id == self.id).data
        if not services:
            self.raise_http_exception(
                status_code="HTTP_404_NOT_FOUND",
                error_case="RECORD_NOT_FOUND",
                message=f"No services found for this module : {str(self.uu_id)}",
                data={
                    "module_uu_id": str(self.uu_id),
                },
            )
        return services

    __table_args__ = ({"comment": "Modules Information"},)


class Services(CrudCollection):
    """
    Services class based on declarative_base and BaseMixin via session
    """

    __tablename__ = "services"
    __exclude__fields__ = []

    module_id: Mapped[int] = mapped_column(ForeignKey("modules.id"), nullable=False)
    module_uu_id: Mapped[str] = mapped_column(
        String, nullable=False, comment="Module UUID"
    )
    service_name: Mapped[str] = mapped_column(
        String, nullable=False, comment="Service Name"
    )
    service_description: Mapped[str] = mapped_column(String, server_default="")
    service_code: Mapped[str] = mapped_column(
        String, nullable=True, comment="Service Code"
    )
    related_responsibility: Mapped[str] = mapped_column(String, server_default="")

    __table_args__ = ({"comment": "Services Information"},)


class Service2Events(CrudCollection):
    """
    Service2Actions class based on declarative_base and BaseMixin via session
    """

    __tablename__ = "services2events"
    __exclude__fields__ = []

    service_id: Mapped[int] = mapped_column(ForeignKey("services.id"), nullable=False)
    service_uu_id = mapped_column(String, nullable=False, comment="Service UUID")
    event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
    event_uu_id = mapped_column(String, nullable=False, comment="Event UUID")

    __table_args__ = ({"comment": "Service2Events Information"},)


class Event2Employee(CrudCollection):
    """
    Employee2Event class based on declarative_base and BaseMixin via session
    """

    __tablename__ = "event2employee"
    __exclude__fields__ = []

    employee_id = mapped_column(ForeignKey("employees.id"), nullable=False)
    employee_uu_id = mapped_column(String, nullable=False, comment="Employee UUID")
    event_id = mapped_column(ForeignKey("events.id"), nullable=False)
    event_uu_id = mapped_column(String, nullable=False, comment="Event UUID")

    __table_args__ = (
        Index("event2employee_employee_to_event", employee_id, event_id, unique=True),
        {"comment": "Employee to Event Information"},
    )

    @classmethod
    def get_event_id_by_employee_id(cls, employee_id) -> (list, list):
        active_events = cls.filter_all(cls.employee_id == employee_id)
        active_events_id = [event.event_id for event in active_events.data]
        active_events = Events.filter_all(Events.id.in_(active_events_id))
        active_events_uu_id = [str(event.uu_id) for event in active_events.data]
        return active_events_id, active_events_uu_id


class Event2Occupant(CrudCollection):
    """
    Occupant2Event class based on declarative_base and BaseMixin via session
    """

    __tablename__ = "event2occupant"
    __exclude__fields__ = []

    build_living_space_id = mapped_column(
        ForeignKey("build_living_space.id"), nullable=False
    )
    build_living_space_uu_id = mapped_column(
        String, nullable=False, comment="Build Living Space UUID"
    )
    event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
    event_uu_id = mapped_column(String, nullable=False, comment="Event UUID")

    __table_args__ = (
        Index(
            "event2occupant_bind_event_to_occupant",
            build_living_space_id,
            event_id,
            unique=True,
        ),
        {"comment": "Occupant2Event Information"},
    )

    @classmethod
    def get_event_id_by_build_living_space_id(
        cls, build_living_space_id
    ) -> (list, list):
        active_events = cls.filter_all(
            cls.build_living_space_id == build_living_space_id,
        ).data
        active_events_id = [event.event_id for event in active_events]
        active_events = Events.filter_all(Events.id.in_(active_events_id)).data
        active_events_uu_id = [str(event.uu_id) for event in active_events]
        return active_events_id, active_events_uu_id


# Delete later code
class ModulePrice(CrudCollection):
    """
    ModulePrice class based on declarative_base and BaseMixin via session
    """

    __tablename__ = "module_price"
    __exclude__fields__ = []

    campaign_code = mapped_column(String, nullable=False, comment="Campaign Code")
    module_id: Mapped[int] = mapped_column(ForeignKey("modules.id"), nullable=False)
    module_uu_id = mapped_column(String, nullable=False, comment="Module UUID")
    service_id: Mapped[int] = mapped_column(ForeignKey("services.id"), nullable=False)
    service_uu_id = mapped_column(String, nullable=False, comment="Service UUID")
    event_id: Mapped[int] = mapped_column(ForeignKey("events.id"), nullable=False)
    event_uu_id = mapped_column(String, nullable=False, comment="Event UUID")
    is_counted_percentage: Mapped[float] = mapped_column(
        Numeric(6, 2), server_default="0.00"
    )  # %22
    discounted_price = mapped_column(
        Numeric(20, 2), server_default="0.00"
    )  # Normal: 78.00 TL
    calculated_price = mapped_column(
        Numeric(20, 2), server_default="0.00"
    )  # sana düz 75.00 TL yapar

    __table_args__ = ({"comment": "ModulePrice Information"},)


#
# class Modules2Occupant(CrudCollection):
#     """
#     ModulesOccupantPrices class based on declarative_base and BaseMixin via session
#     discounted_price - calculated_price = Pazarlamaya gider yazılır 3 TL
#     """
#
#     __tablename__ = "modules2_occupant"
#
#
#     discounted_percentage: Mapped[float] = mapped_column(Numeric(6, 2), server_default="0.00")  # %22
#     discounted_price = mapped_column(
#         Numeric(20, 2), server_default="0.00"
#     )  # Normal: 78.00 TL
#     calculated_price = mapped_column(
#         Numeric(20, 2), server_default="0.00"
#     )  # sana düz 75.00 TL yapar
#
#     service_id = mapped_column(ForeignKey("services.id"), nullable=False)
#     build_living_space_id = mapped_column(
#         ForeignKey("build_living_space.id"), nullable=False, index=True
#     )
#
#     __table_args__ = ({"comment": "ModulesOccupantPrices Information"},)
#
#
# class Modules2Employee(CrudCollection):
#     """
#     Modules2EmployeeServices class based on declarative_base and BaseMixin via session
#     """
#
#     __tablename__ = "modules2_employee"
#
#     discounted_percentage: Mapped[float] = mapped_column(Numeric(6, 2), server_default="0.00")  # %22
#     discounted_price = mapped_column(
#         Numeric(20, 2), server_default="0.00"
#     )  # Normal: 78.00 TL
#     calculated_price = mapped_column(
#         Numeric(20, 2), server_default="0.00"
#     )  # sana düz 75.00 TL yapar
#
#     service_id = mapped_column(ForeignKey("services.id"), nullable=False)
#     employee_id = mapped_column(ForeignKey("employees.id"), nullable=False)
#
#     __table_args__ = ({"comment": "Modules2EmployeeServices Information"},)
# class Actions(CrudCollection):
#     """
#     Actions class based on declarative_base and BaseMixin via session
#     """
#
#     __tablename__ = "actions"
#     __exclude__fields__ = []
#
#     action_table = mapped_column(String, nullable=False, comment="Action Table")
#     action_type = mapped_column(String, nullable=False, comment="Action Type")
#     action_description = mapped_column(String, server_default="")
#     action_code = mapped_column(String, nullable=False, comment="Action Code")
#     endpoint_id = mapped_column(ForeignKey("endpoint_restriction.id"), nullable=True)
#     endpoint_uu_id = mapped_column(String, nullable=True, comment="Endpoint UUID")
#
#     @property
#     def action_name(self):
#         return f"{self.action_table} {self.action_type}"
#
#     @property
#     def total_cost(self):
#         return self.cost * self.unit_price
#
#     __table_args__ = ({"comment": "Actions Information"},)
