"""This module defines the SQL data model for users.

All users are either Patients or Administrators.
"""

import enum

from sqlalchemy import Column, ForeignKey, Integer, String, DateTime, Date, Enum, CheckConstraint
from sqlalchemy.sql.functions import now
from sqlalchemy.orm import relationship

from backend.database.engine import Base
from backend.models.devices import Device


class User(Base):
    """Model for the users table. Contains user info common to all user classes."""

    __tablename__ = "users"

    id = Column('id', Integer, primary_key=True, autoincrement=True, index=True)
    email = Column('email', String, unique=True, nullable=False)
    password = Column('password', String, nullable=False)
    created = Column('created', DateTime(timezone=True), nullable=False, server_default=now())
    updated = Column('updated', DateTime(timezone=True), nullable=False, server_default=now(), onupdate=now())
    first_name = Column('first_name', String, nullable=False)
    last_name = Column('last_name', String, nullable=False)

    administrator = relationship("Administrator", back_populates="user", uselist=False, cascade="all, delete")
    patient = relationship("Patient", back_populates="user", uselist=False, cascade="all, delete")


class Administrator(Base):
    """Model for the administrators table. Contains user info specific to administrators."""

    __tablename__ = "administrators"

    user_id = Column('user_id', Integer, ForeignKey('users.id', ondelete="CASCADE"), primary_key=True)
    user = relationship(User, back_populates="administrator", uselist=False, cascade="all, delete")


class Gender(enum.Enum):
    """Gender (as assigned at birth) of a patient."""

    male = 'm'
    female = 'f'


class Patient(Base):
    """Model for the patients table. Contains user info specific to patients."""

    __tablename__ = "patients"

    user_id = Column('user_id', Integer, ForeignKey('users.id', ondelete="CASCADE"), primary_key=True)
    date_of_birth = Column('date_of_birth', Date, nullable=False)
    gender = Column('gender', Enum(Gender), nullable=False)

    user = relationship(User, back_populates="patient", uselist=False, cascade="all, delete")
    devices = relationship(Device, back_populates="owner", uselist=True, cascade="all, delete")
