import uuid
from datetime import datetime, timezone

from sqlalchemy import String, Boolean, Integer, DateTime, Text, func, ForeignKey, Uuid
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.database import Base


class User(Base):
    __tablename__ = "users"
    __table_args__ = {"extend_existing": True}

    id: Mapped[str] = mapped_column(Text, primary_key=True)
    email: Mapped[str] = mapped_column(Text, unique=True, nullable=False)
    phone: Mapped[str | None] = mapped_column(Text, nullable=True)
    username: Mapped[str | None] = mapped_column(Text, nullable=True)
    password: Mapped[str] = mapped_column(Text, nullable=False)
    firstName: Mapped[str | None] = mapped_column(Text, nullable=True)
    lastName: Mapped[str | None] = mapped_column(Text, nullable=True)
    avatar: Mapped[str | None] = mapped_column(Text, nullable=True)
    isActive: Mapped[bool] = mapped_column(Boolean, default=True)
    emailVerified: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    phoneVerified: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    lastLoginAt: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    createdAt: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    updatedAt: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=func.now(), onupdate=func.now(), nullable=False)
    mfaSecret: Mapped[str | None] = mapped_column(Text, nullable=True)
    mfaEnabled: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    loginAttempts: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    lockedUntil: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    organization_id: Mapped[uuid.UUID | None] = mapped_column(Uuid(as_uuid=True), ForeignKey("organizations.id", ondelete="SET NULL"), nullable=True)
    role: Mapped[str] = mapped_column(String(20), server_default="owner", nullable=False)
    plan: Mapped[str] = mapped_column(String(20), server_default="free", nullable=False)
    max_queries: Mapped[int] = mapped_column(Integer, server_default="5", nullable=False)

    queries: Mapped[list["Query"]] = relationship(
        "Query", back_populates="user", viewonly=True,
        primaryjoin="User.id == foreign(Query.user_id)",
    )
    subscriptions: Mapped[list["Subscription"]] = relationship(
        "Subscription", back_populates="user", viewonly=True,
        primaryjoin="User.id == foreign(Subscription.user_id)",
    )
    organization: Mapped["Organization | None"] = relationship(
        "Organization", secondary="org_members", viewonly=True, uselist=False,
    )
    org_memberships: Mapped[list["OrgMember"]] = relationship(
        "OrgMember", back_populates="user", viewonly=True,
        primaryjoin="User.id == foreign(OrgMember.user_id)",
    )

    @property
    def name(self) -> str | None:
        if self.firstName and self.lastName:
            return f"{self.firstName} {self.lastName}"
        return self.username or self.firstName

    @property
    def is_admin(self) -> bool:
        return False

    @property
    def is_active(self) -> bool:
        return self.isActive

    @property
    def email_verified(self) -> bool:
        return self.emailVerified

    @property
    def avatar_url(self) -> str | None:
        return self.avatar

    @property
    def password_hash(self) -> str:
        return self.password
