import sqlmodel
import sqlmodel.sql._expression_select_cls

from .product import product
from .reservation import reservation
from .reservation import reservation_factory
from .reservations_collection import reservations_collection

class reservation_loader(sqlmodel.Session): 
    def get_by_email(self, target: str) -> reservations_collection:
        return self.__get(reservation.email == target)
    
    def get_by_phone_number(self, target: str) -> reservations_collection:
        return self.__get(reservation.phone_number == target)

    def get_by_target(self, target: product) -> reservations_collection:
        if not target.in_database:
            return reservations_collection()

        return self.__get(reservation.target == target)

    def __get(self, condition: object) -> reservations_collection:
        query = self.__select.where(condition)
        collection = reservations_collection()
        result = self.exec(query)

        for item in result:
            collection.append(item)

        return collection

    def store(self, target: reservation) -> bool:
        if not target.ready:
            raise RuntimeError("Reservation is not setup.")

        if target.in_database:
            error = "Target reservation is already in database. Reservation "
            error = error + "object is not editable."

            raise reservation_loader_exception(error)

        try:
            self.add(target)
            self.commit()
            self.refresh(target)

            return True
        
        except:
            return False

    def drop(self, target: reservation) -> bool:
        if not target.in_database:
            raise reservation_loader_exception("Reservation does not exists.")

        try:
            self.delete(target)
            self.commit()

            return True

        except:
            return False

    @property
    def __select(self) -> sqlmodel.sql._expression_select_cls.SelectOfScalar:
        return sqlmodel.select(reservation)
