"""Permission checking service — RBAC helpers and FastAPI dependency factory."""

from fastapi import Depends, HTTPException, Request, status
from sqlalchemy.orm import Session

from app.database import get_db
from app.models.permission import Permission, Role, RolePermission
from app.models.user import User
from app.models.user_house_role import UserHouseRole
from app.services.auth_service import get_current_user


def get_user_permissions(
    user_id: str, house_id: str, db: Session
) -> list[str]:
    """Get all permission codes for a user in a specific house context."""
    user_roles = (
        db.query(UserHouseRole)
        .filter(
            UserHouseRole.user_id == user_id,
            UserHouseRole.house_id == house_id,
        )
        .all()
    )

    permission_codes: list[str] = []
    seen_perm_ids: set[str] = set()

    for uhr in user_roles:
        role_perms = (
            db.query(RolePermission)
            .filter(RolePermission.role_id == uhr.role_id)
            .all()
        )
        for rp in role_perms:
            if rp.permission_id not in seen_perm_ids:
                seen_perm_ids.add(rp.permission_id)
                perm = (
                    db.query(Permission)
                    .filter(Permission.id == rp.permission_id)
                    .first()
                )
                if perm:
                    permission_codes.append(perm.code)

    return permission_codes


def check_permission(
    user_id: str, house_id: str, permission_code: str, db: Session
) -> bool:
    """Check if a user (or admin) has a specific permission in a house."""
    user = db.query(User).filter(User.id == user_id).first()
    if user and user.is_admin:
        return True

    permissions = get_user_permissions(user_id, house_id, db)
    return permission_code in permissions


class require_permission:
    """FastAPI dependency factory for route-level permission checks.

    Usage in a route that has a house context (``hid`` path param)::

        @router.get("/api/houses/{hid}/floors")
        async def list_floors(
            ...,
            _=Depends(require_permission("house.view")),
        ):
    """

    def __init__(self, permission_code: str):
        self.permission_code = permission_code

    async def __call__(
        self,
        request: Request,
        current_user: User = Depends(get_current_user),
        db: Session = Depends(get_db),
    ):
        # Try to extract house_id from path parameters
        house_id = request.path_params.get("hid") or request.path_params.get(
            "house_id"
        )
        if not house_id:
            # Non-house endpoints just require authentication
            return

        if current_user.is_admin:
            return

        if not check_permission(
            current_user.id, house_id, self.permission_code, db
        ):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="权限不足",
            )
