"""
User model for authentication and authorization.
"""
import enum
from sqlalchemy import Column, String, Boolean, Enum, Integer, ForeignKey, Table, Enum as SQLEnum
from sqlalchemy.orm import relationship

from app.models.base import BaseModel
from app.database import Base


class UserRole(str, enum.Enum):
    """User roles for authorization."""
    SUPERADMIN = "superadmin"  # Can manage all establishments
    ADMIN = "admin"  # Can manage settings for assigned establishments
    MANAGER = "manager"  # Can manage operations for assigned establishments
    RECEPTION = "reception"
    ACCOUNTING = "accounting"


# Association table for User-Establishment many-to-many relationship
user_establishments = Table(
    'user_establishments',
    Base.metadata,
    Column('user_id', Integer, ForeignKey('users.id', ondelete='CASCADE'), primary_key=True),
    Column('establishment_id', Integer, ForeignKey('establishments.id', ondelete='CASCADE'), primary_key=True)
)


class User(BaseModel):
    """
    User model for authentication.

    Attributes:
        email: Unique email address
        hashed_password: Bcrypt hashed password
        first_name: User's first name
        last_name: User's last name
        role: User role (superadmin, admin, manager, reception, accounting)
        is_active: Whether user can login
        establishment_id: Default establishment (optional, for backward compatibility)
    """
    __tablename__ = "users"

    email = Column(String(255), unique=True, index=True, nullable=False)
    hashed_password = Column(String(255), nullable=False)
    first_name = Column(String(100), nullable=False)
    last_name = Column(String(100), nullable=False)
    role = Column(
        Enum(UserRole, name='userrole', create_type=False, native_enum=True, values_callable=lambda x: [e.value for e in x]),
        default=UserRole.RECEPTION,
        nullable=False
    )
    is_active = Column(Boolean, default=True, nullable=False)
    establishment_id = Column(
        Integer,
        ForeignKey("establishments.id", ondelete="SET NULL"),
        nullable=True
    )

    # Relationships
    establishment = relationship("Establishment", back_populates="users")
    # Many-to-many relationship with establishments
    establishments = relationship(
        "Establishment",
        secondary=user_establishments,
        backref="authorized_users"
    )

    @property
    def full_name(self) -> str:
        """Return user's full name."""
        return f"{self.first_name} {self.last_name}"

    @property
    def is_superadmin(self) -> bool:
        """Check if user is superadmin."""
        return self.role == UserRole.SUPERADMIN

    @property
    def is_admin(self) -> bool:
        """Check if user is admin or superadmin."""
        return self.role in [UserRole.SUPERADMIN, UserRole.ADMIN]

    def has_access_to_establishment(self, establishment_id: int) -> bool:
        """Check if user has access to a specific establishment."""
        if self.is_superadmin:
            return True
        return any(e.id == establishment_id for e in self.establishments)

    def __repr__(self) -> str:
        return f"<User {self.email}>"
