class GrantIn(BaseModel):
    user_id: int


def _grant_json(grant, users, categories):
    user = users.get(grant.user_id)
    return {
        "id": grant.id,
        "category_id": grant.category_id,
        "category_name": categories.get(grant.category_id),
        "user_id": grant.user_id,
        "user_name": user.name if user else None,
        "user_email": user.email if user else None,
        "created_at": grant.created_at.isoformat() if grant.created_at else None,
    }


@router.get("/grants")
def list_category_grants(
    db: Session = Depends(get_db),
    current_user: User = Depends(require_moderator),
):
    """Every per-category editorial grant, for the question-manager admin panel."""
    grants = db.query(CategoryGrant).order_by(CategoryGrant.id).all()
    categories = {cat.id: cat.name for cat in db.query(QuestionCategory).all()}
    users = {user.id: user for user in db.query(User).filter(
        User.id.in_({g.user_id for g in grants}))} if grants else {}
    return [_grant_json(grant, users, categories) for grant in grants]


@router.post("/{cat_id}/grants", status_code=201)
def add_category_grant(
    cat_id: int,
    data: GrantIn,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_moderator),
):
    """Let one user edit the questions in this category and everything under it."""
    category = db.get(QuestionCategory, cat_id)
    if not category:
        raise HTTPException(404, "Category not found")
    user = db.get(User, data.user_id)
    if not user:
        raise HTTPException(404, "User not found")
    if user.is_moderator:
        raise HTTPException(400, "Moderators already manage every category")
    existing = db.query(CategoryGrant).filter_by(category_id=cat_id, user_id=data.user_id).first()
    if existing:
        raise HTTPException(409, "This user already has a grant for this category")
    grant = CategoryGrant(category_id=cat_id, user_id=data.user_id, granted_by=current_user.id)
    db.add(grant)
    db.commit()
    db.refresh(grant)
    return _grant_json(grant, {user.id: user}, {category.id: category.name})


@router.delete("/{cat_id}/grants/{user_id}", status_code=204)
def remove_category_grant(
    cat_id: int,
    user_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_moderator),
):
    grant = db.query(CategoryGrant).filter_by(category_id=cat_id, user_id=user_id).first()
    if not grant:
        raise HTTPException(404, "Grant not found")
    db.delete(grant)
    db.commit()


@router.get("/my-grants")
def my_category_grants(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """What the signed-in user may edit — drives the question-manager entry point."""
    scope = manageable_categories(db, current_user)
    if scope is None:
        return {"is_moderator": True, "can_manage_questions": True, "categories": []}
    names = {cat.id: cat.name for cat in db.query(QuestionCategory).filter(
        QuestionCategory.id.in_(scope))} if scope else {}
    granted = {row[0] for row in db.query(CategoryGrant.category_id).filter(
        CategoryGrant.user_id == current_user.id).all()}
    return {
        "is_moderator": False,
        "can_manage_questions": bool(scope),
        "categories": sorted(
            ({"id": cid, "name": names.get(cid), "direct": cid in granted} for cid in scope),
            key=lambda row: (row["name"] or ""),
        ),
    }


