from uuid import UUID

from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession

from src.apps.notifications.constants import NotificationScope
from src.apps.notifications.schemas.notification import NotificationResponse
from src.apps.notifications.services.notification_service import NotificationService
from src.core.constants import UserRole
from src.core.dependencies import require_min_role
from src.core.exceptions import NotFoundError
from src.core.schemas.response import paginated, success
from src.database.session import get_db

router = APIRouter(prefix="/notifications", tags=["Notifications"])


@router.get("", response_model=dict)
async def list_notifications(
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    unread_only: bool = Query(False),
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    db: AsyncSession = Depends(get_db),
):
    """Newest-first notifications for the caller's tenant. All users in a tenant
    share one notification stream — it is not filtered per-user."""
    service = NotificationService(db)
    items, total = await service.list(
        scope=NotificationScope.TENANT,
        tenant_id=current_user.tenant_id,
        page=page,
        page_size=page_size,
        unread_only=unread_only,
    )
    return paginated(
        items=[NotificationResponse.model_validate(n).model_dump() for n in items],
        total=total,
        page=page,
        page_size=page_size,
    )


@router.get("/unread-count", response_model=dict)
async def get_unread_count(
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    db: AsyncSession = Depends(get_db),
):
    """Badge count. Cheap enough to poll as a WebSocket safety net."""
    service = NotificationService(db)
    count = await service.count_unread(
        scope=NotificationScope.TENANT,
        tenant_id=current_user.tenant_id,
    )
    return success(data={"count": count})


@router.patch("/{notification_id}/read", response_model=dict)
async def mark_notification_read(
    notification_id: UUID,
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    db: AsyncSession = Depends(get_db),
):
    service = NotificationService(db)
    notification = await service.mark_read(
        notification_id,
        scope=NotificationScope.TENANT,
        tenant_id=current_user.tenant_id,
    )
    if notification is None:
        raise NotFoundError("Notification not found")
    return success(
        data=NotificationResponse.model_validate(notification).model_dump(),
        message="Notification marked as read",
    )


@router.post("/mark-all-read", response_model=dict)
async def mark_all_notifications_read(
    current_user=Depends(require_min_role(UserRole.VIEW_ONLY)),
    db: AsyncSession = Depends(get_db),
):
    service = NotificationService(db)
    updated = await service.mark_all_read(
        scope=NotificationScope.TENANT,
        tenant_id=current_user.tenant_id,
    )
    return success(data={"updated": updated}, message="All notifications marked as read")
