from datetime import datetime
from typing import Optional
from sqlalchemy import Integer, String, DateTime, ForeignKey, Index
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.sql import func
from src.apps.base.models.base import Base


class MerchantInvite(Base):
    """
    MerchantInvite Model: Tracks pending invitations to join a merchant account.
    Token is stored as a SHA-256 hash; the raw token is sent via email only.
    """

    __tablename__ = "merchant_invites"
    __table_args__ = (Index("ix_merchant_invites_token_hash", "token_hash"),)

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    merchant_id: Mapped[int] = mapped_column(Integer, ForeignKey("merchants.id"), nullable=False, index=True)
    email: Mapped[str] = mapped_column(String(255), nullable=False)
    role_id: Mapped[int] = mapped_column(Integer, ForeignKey("roles.id"), nullable=False)
    token_hash: Mapped[str] = mapped_column(String(64), nullable=False)
    invited_by: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"), nullable=False)
    expires_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
    accepted_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    cancelled_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())

    role: Mapped["Role"] = relationship("Role", foreign_keys=[role_id], uselist=False, lazy="joined")
    inviter: Mapped["User"] = relationship("User", foreign_keys=[invited_by], uselist=False)

    @property
    def is_expired(self) -> bool:
        from datetime import timezone
        now = datetime.now(timezone.utc).replace(tzinfo=None)
        return now > self.expires_at

    @property
    def is_pending(self) -> bool:
        return self.accepted_at is None and self.cancelled_at is None and not self.is_expired
