import bcrypt
from flask_login import UserMixin

from app.extensions import db


class User(db.Model, UserMixin):
    __tablename__ = "users"

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password_hash = db.Column(db.String(255), nullable=False)
    full_name = db.Column(db.String(120), nullable=False)
    role = db.Column(db.String(20), nullable=False, default="salesperson")  # 'admin' | 'salesperson'
    is_active_flag = db.Column("is_active", db.Boolean, nullable=False, default=True)
    created_at = db.Column(db.DateTime, nullable=False, server_default=db.func.now())

    permissions = db.relationship(
        "Permission", backref="user", cascade="all, delete-orphan", lazy="selectin"
    )

    # UserMixin.is_active از پراپرتی زیر می‌خونه (نمی‌تونستیم ستون رو مستقیم is_active اسم بذاریم
    # چون UserMixin خودش is_active رو به‌عنوان پراپرتی همیشه-True تعریف کرده)
    @property
    def is_active(self):
        return self.is_active_flag

    def set_password(self, plain: str):
        self.password_hash = bcrypt.hashpw(plain.encode("utf-8"), bcrypt.gensalt()).decode("utf-8")

    def check_password(self, plain: str) -> bool:
        try:
            return bcrypt.checkpw(plain.encode("utf-8"), self.password_hash.encode("utf-8"))
        except ValueError:
            return False

    def permission_keys(self) -> set:
        return {p.page_key for p in self.permissions}

    def is_admin(self) -> bool:
        return self.role == "admin"


class Permission(db.Model):
    __tablename__ = "permissions"

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
    page_key = db.Column(db.String(50), nullable=False)

    __table_args__ = (db.UniqueConstraint("user_id", "page_key", name="uq_user_page"),)
