"""The one inbox: what the bell polls, and marking rows read.

Sources of truth: this module, `app/services/discussion.py` (the event emission, the inbox
read), `app/models/discussion.py` (`Notification`), `docs/ACCOUNTS.md` (Notifications).

Local today, the same shape a shared inbox service would serve, so the bell repoints rather
than migrates. The inbox is the EFFECTIVE account's (a View As shows the target's bell, which
is what viewing as someone means); marking read is a write, so read-only View As is refused
by the access policy like every other write. Any signed-in account may read its own inbox;
what lands in it was already scoped by the subject's permission when it was emitted.
"""

from fastapi import APIRouter, Depends, Request
from pydantic import BaseModel
from sqlalchemy.orm import Session

from app.db import get_db
from app.models.discussion import AccountPreference
from app.services import discussion as disc
from app.services import identity

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


class ReadIn(BaseModel):
    ids: list[int] | None = None


@router.get("")
def inbox(request: Request, db: Session = Depends(get_db)) -> dict:
    """The newest forty rows, unread first, with the unread count and whether any unread row
    is addressed to the reader personally (a mention)."""
    return disc.inbox(db, identity.actor(request).id)


@router.post("/read")
def mark_read(payload: ReadIn, request: Request, db: Session = Depends(get_db)) -> dict:
    """Mark the given rows read, or every unread row when none are named."""
    n = disc.mark_read(db, identity.actor(request).id, payload.ids)
    db.commit()
    return {"ok": True, "read": n}


class PreferencesOut(BaseModel):
    mail_notifications: bool


class PreferencesIn(BaseModel):
    mail_notifications: bool


@router.get("/preferences", response_model=PreferencesOut)
def preferences(request: Request, db: Session = Depends(get_db)) -> PreferencesOut:
    """Whether the digest mails this person; the default is yes until they say otherwise."""
    row = db.get(AccountPreference, identity.actor(request).id)
    return PreferencesOut(mail_notifications=row.mail_notifications if row else True)


@router.post("/preferences", response_model=PreferencesOut)
def set_preferences(payload: PreferencesIn, request: Request, db: Session = Depends(get_db)) -> PreferencesOut:
    who = identity.actor(request)
    row = db.get(AccountPreference, who.id)
    if row is None:
        row = AccountPreference(account_id=who.id)
        db.add(row)
    row.mail_notifications = payload.mail_notifications
    db.commit()
    return PreferencesOut(mail_notifications=row.mail_notifications)
