"""The bell — the local inbox (Interaction Standard §6 embryo). Polled by the
SPA (30s, backing off when the tab is hidden). needs_you = any unread item is a
mention or a turn: something is actually asked of you."""

from fastapi import APIRouter, Depends
from sqlalchemy import select

from app import schemas
from app.db import get_session_factory
from app.identity import optional_user
from app.models import Notification
from app.services.projects import utcnow

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


def _user(user: str | None = Depends(optional_user)) -> str:
    assert user is not None
    return user


@router.get("", response_model=schemas.NotificationListOut)
def list_notifications(user: str = Depends(_user),
                       limit: int = 50) -> schemas.NotificationListOut:
    sf = get_session_factory()
    with sf() as db:
        rows = list(db.scalars(
            select(Notification).where(Notification.recipient == user)
            .order_by(Notification.occurred_at.desc(), Notification.id.desc())
            .limit(min(max(limit, 1), 200))))
        unread = [n for n in rows if n.read_at is None]
        return schemas.NotificationListOut(
            notifications=[schemas.NotificationOut(
                id=n.id, actor=n.actor, app=n.app, kind=n.kind,
                category=n.category, context_label=n.context_label,
                body=n.body, url=n.url, project_id=n.project_id,
                occurred_at=n.occurred_at, read=n.read_at is not None,
            ) for n in rows],
            unread=len(unread),
            needs_you=any(n.kind in ("mention", "turn") for n in unread))


@router.post("/read", response_model=schemas.OkOut)
def mark_read(body: schemas.MarkReadIn, user: str = Depends(_user)) -> schemas.OkOut:
    sf = get_session_factory()
    with sf() as db:
        now = utcnow()
        for n in db.scalars(select(Notification).where(
                Notification.recipient == user,
                Notification.id.in_(body.ids or []))):
            if n.read_at is None:
                n.read_at = now
        db.commit()
    return schemas.OkOut()
