import sqlmodel

from .product import product
from .exception import reservation_exception
from .validator import phone_number_validator
from .validator import email_validator

class reservation(sqlmodel.SQLModel, table = True):
    __tablename__: str = "reservation"

    id: int | None = sqlmodel.Field(default = None, primary_key = True)
    
    email: str | None = sqlmodel.Field(
        default = None,
        index = True,
        unique = False
    )

    phone_number: str | None = sqlmodel.Field(
        default = None,
        index = True,
        unique = False
    )

    target_id: int | None = sqlmodel.Field(
        default = None, 
        foreign_key = "product.id",
        unique = False
    ) 

    target: product | None = sqlmodel.Relationship(
        back_populates = "reservations"
    )

    @property 
    def in_database(self) -> bool:
        return self.id is not None

    @property
    def ready(self) -> bool:
        if self.target is None:
            return False

        if self.email is None and self.phone_number is None:
            return False
        
        return True

    def __str__(self) -> str:
        content = "Reservation "

        if self.in_database:
            content = content + "#" + str(self.id)
        
        content = content + "\n"
        
        if self.email is not None:
            content = content + "E-mail: \"" + self.email + "\"\n"
        
        if self.phone_number is not None:
            content = content + "Phone: \"" + self.phone_number + "\"\n"
        
        if self.target is None:
            return content + "Target: not set"

        return content + "Target: #" + str(self.target.id) + "\n"
    
class reservation_factory:
    def __init__(self, target: reservation | None = None) -> None:
        self.__target = target

        if self.__target is None:
            self.__target = reservation()

    def target(self, item: product) -> object:
        if not item.in_database:
            raise reservation_exception("Target item not in database.")

        self.__target.target = item
        return self

    def phone_number(self, number: str) -> object:
        if not phone_number_validator(number).result:
            raise reservation_exception("Phone number is not valid.")

        self.__target.phone_number = number
        return self

    def email(self, email: str) -> object:
        if not email_validator(email).result:
            raise reservation_exception("Email is not valid.")

        self.__target.email = email
        return self
    
    def result(self) -> reservation:
        return self.__target

        
