from fastapi import HTTPException, Request
from bson.objectid import ObjectId
from model.staff_model import StaffModel, collection
from typing import Optional

async def get_current_actor_optional(request: Request):
    """
    Cố gắng lấy actor hiện tại từ Authorization header.
    Không raise lỗi ngay, để middleware log vẫn ghi được cả request thất bại.
    """
    auth_header = request.headers.get("Authorization")
    if not auth_header or not auth_header.startswith("Bearer "):
        return None

    user_id = auth_header.split(" ")[1]

    # Admin fake để test
    if user_id == "1":
        actor = {
            "id": "1",
            "role": "admin",
            "permissions": ["admin"],
            "name": "Admin",
            "email": ""
        }
        request.state.actor = actor
        return actor

    # Tìm staff trong MongoDB
    try:
        user = collection.find_one({"_id": ObjectId(user_id), "role": "staff"})
    except Exception:
        user = collection.find_one({"id": user_id, "role": "staff"})

    if not user:
        return None

    actor = {
        "id": str(user.get("_id", user.get("id"))),
        "role": user.get("role", "staff"),
        "permissions": user.get("permissions", []),
        "name": user.get("name", "Staff"),
        "email": user.get("email", ""),
        "status": user.get("status", "inactive")
    }

    request.state.actor = actor
    return actor


async def get_current_actor_required(request: Request):
    """
    Dùng cho các API cần chặn quyền thật sự.
    Nếu không có actor hoặc actor không hợp lệ thì raise 401/403.
    """
    actor = await get_current_actor_optional(request)

    if not actor:
        raise HTTPException(status_code=401, detail="Unauthorized")

    # Admin fake luôn active
    if actor.get("role") != "admin" and actor.get("status") != "active":
        raise HTTPException(status_code=403, detail="Account is inactive")

    return actor


def requires_permission(permission_name: str):
    async def dependency(request: Request):
        # Ghi lại permission yêu cầu để middleware log dùng được
        request.state.required_permission = permission_name

        current_user = await get_current_actor_required(request)

        # Admin fake full quyền
        if current_user["role"] == "admin":
            return current_user

        # Staff có permission "admin" hoặc permission cụ thể thì được qua
        if StaffModel.check_access(current_user["permissions"], permission_name):
            return current_user

        raise HTTPException(status_code=403, detail="Forbidden: No permission")

    return dependency

def assert_actor_match(current_user: dict, client_actor_id: Optional[str]):
    expected_actor_id = str((current_user or {}).get("id") or "").strip()
    actual_actor_id = str(client_actor_id or "").strip()

    if not expected_actor_id:
        raise HTTPException(status_code=401, detail="Unauthorized")

    if not actual_actor_id:
        raise HTTPException(status_code=400, detail="actorId is required")

    if actual_actor_id != expected_actor_id:
        raise HTTPException(status_code=403, detail="Forbidden: actor mismatch")

    return expected_actor_id