
from sqlalchemy.orm import Session, joinedload

from app.crud.base import CRUDBase
from app.models.role import Role
from app.models.role_menu import RoleMenu
from app.schemas.role import RoleCreate, RoleUpdate
from common_logging import get_logger

logger = get_logger(__name__)


class CRUDRole(CRUDBase[Role, RoleCreate, RoleUpdate]):

    def get_multi(self, db: Session, *, skip: int = 0, limit: int = 100, **kwargs) -> list[Role]:
        query = db.query(self.model).filter(not self.model.is_deleted)
        return query.offset(skip).limit(limit).all()

    def get_by_code(self, db: Session, *, code: str) -> Role | None:
        return db.query(Role).filter(Role.code == code, not Role.is_deleted).first()

    def get_menus(self, db: Session, *, role_id: int) -> list[int]:
        role_menus = (
            db.query(RoleMenu)
            .filter(RoleMenu.role_id == role_id, not RoleMenu.is_deleted)
            .all()
        )
        return [rm.menu_id for rm in role_menus]

    def update_menus(self, db: Session, *, role_id: int, menu_ids: list[int]) -> None:
        existing = (
            db.query(RoleMenu)
            .filter(RoleMenu.role_id == role_id, not RoleMenu.is_deleted)
            .all()
        )
        for rm in existing:
            rm.is_deleted = True
        for menu_id in menu_ids:
            role_menu = RoleMenu(role_id=role_id, menu_id=menu_id)
            db.add(role_menu)
        db.commit()
        logger.bind(role_id=role_id).info("Role menus updated")

    def get_with_menus(self, db: Session, *, role_id: int) -> Role | None:
        return (
            db.query(Role)
            .options(joinedload(Role.role_menus))
            .filter(Role.id == role_id, not Role.is_deleted)
            .first()
        )


role = CRUDRole(Role)
