from datetime import datetime

from sqlalchemy import DateTime, ForeignKey, Integer, String, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.db.base import Base, SoftDeleteMixin, TimestampMixin
from app.db.types import str_enum
from app.models.enums import UserRole


class User(Base, TimestampMixin, SoftDeleteMixin):
    __tablename__ = "users"
    __table_args__ = (UniqueConstraint("email", name="uq_users_email"),)

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    agency_id: Mapped[int] = mapped_column(ForeignKey("agencies.id"), nullable=False, index=True)
    email: Mapped[str] = mapped_column(String(255), nullable=False)
    full_name: Mapped[str] = mapped_column(String(255), nullable=False)
    hashed_password: Mapped[str] = mapped_column(String(255), nullable=False)
    role: Mapped[UserRole] = mapped_column(str_enum(UserRole), nullable=False, default=UserRole.AGENT)
    mobile: Mapped[str | None] = mapped_column(String(20), nullable=True)
    is_active: Mapped[bool] = mapped_column(default=True, nullable=False)
    failed_login_attempts: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    locked_until: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)

    agency: Mapped["Agency"] = relationship(back_populates="users")
    notifications: Mapped[list["Notification"]] = relationship(back_populates="user")
    notification_preferences: Mapped["UserNotificationPreference | None"] = relationship(
        back_populates="user", uselist=False
    )
    device_push_tokens: Mapped[list["DevicePushToken"]] = relationship(back_populates="user")


from app.models.agency import Agency  # noqa: E402
from app.models.device_push_token import DevicePushToken  # noqa: E402
from app.models.notification import Notification  # noqa: E402
from app.models.user_notification_preference import UserNotificationPreference  # noqa: E402
