import enum

from sqlalchemy import Boolean, ForeignKey, String, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.models.base import Base, SoftDeleteMixin, TimestampMixin


class ModulEnum(str, enum.Enum):
    dashboard = "dashboard"
    penjualan = "penjualan"
    stock = "stock"
    penebusan = "penebusan"
    penerimaan = "penerimaan"
    expenses = "expenses"
    penyetoran = "penyetoran"
    rekonsiliasi = "rekonsiliasi"
    laporan = "laporan"
    analytics = "analytics"
    anomali = "anomali"
    products = "products"
    tangki = "tangki"
    spbu_settings = "spbu_settings"
    contracts = "contracts"
    users = "users"
    spbu_management = "spbu_management"
    operators = "operators"
    jadwal = "jadwal"
    absensi = "absensi"
    housekeeping = "housekeeping"
    sapras = "sapras"


class AksiEnum(str, enum.Enum):
    view = "view"
    create = "create"
    edit = "edit"
    delete = "delete"
    export = "export"
    approve = "approve"


class Role(Base, TimestampMixin, SoftDeleteMixin):
    __tablename__ = "master_role"

    id: Mapped[int] = mapped_column(primary_key=True)
    spbu_id: Mapped[int | None] = mapped_column(
        ForeignKey("master_spbu.id", ondelete="CASCADE"), nullable=True, index=True
    )
    nama: Mapped[str] = mapped_column(String(100))
    deskripsi: Mapped[str | None] = mapped_column(Text, nullable=True)
    is_system: Mapped[bool] = mapped_column(Boolean, default=False)
    can_be_scheduled: Mapped[bool] = mapped_column(Boolean, default=False)
    can_login_web: Mapped[bool] = mapped_column(Boolean, default=True)

    permissions: Mapped[list["RolePermission"]] = relationship(
        back_populates="role", cascade="all, delete-orphan"
    )
    assignments: Mapped[list["UserSpbuAssignment"]] = relationship(
        back_populates="role"
    )


class RolePermission(Base):
    __tablename__ = "master_role_permission"
    __table_args__ = (UniqueConstraint("role_id", "modul", "aksi"),)

    id: Mapped[int] = mapped_column(primary_key=True)
    role_id: Mapped[int] = mapped_column(
        ForeignKey("master_role.id", ondelete="CASCADE"), index=True
    )
    modul: Mapped[ModulEnum]
    aksi: Mapped[AksiEnum]

    role: Mapped["Role"] = relationship(back_populates="permissions")


class UserSpbuAssignment(Base, TimestampMixin):
    __tablename__ = "master_user_spbu_assignment"
    __table_args__ = (UniqueConstraint("user_id", "spbu_id"),)

    id: Mapped[int] = mapped_column(primary_key=True)
    user_id: Mapped[int] = mapped_column(
        ForeignKey("master_user.id", ondelete="CASCADE"), index=True
    )
    spbu_id: Mapped[int] = mapped_column(
        ForeignKey("master_spbu.id", ondelete="CASCADE"), index=True
    )
    role_id: Mapped[int] = mapped_column(ForeignKey("master_role.id", ondelete="RESTRICT"))

    user: Mapped["User"] = relationship(back_populates="assignments")
    spbu: Mapped["Spbu"] = relationship(back_populates="assignments")
    role: Mapped["Role"] = relationship(back_populates="assignments")


from app.models.user import User  # noqa: E402, F401
from app.models.spbu import Spbu  # noqa: E402, F401
