"""Reports: a feed of finished work, and one report on its own page.

List-plus-detail, the same shape as the library — and for the same reason, since
an instance running a daily schedule accumulates reports faster than anything
else here.

**There is no composer on either page, and no route below accepts a message.**
That is the whole character of the section rather than an omission: a report is
addressed to the reader and cannot be answered, and the way to be sure of that
is for the machinery that would answer to be absent. Nothing here renders
`chat/_message.html`, so there is no `sse-connect` anywhere on these pages and
nothing on them can start a generation.
"""

from __future__ import annotations

import logging

from fastapi import APIRouter, Depends, HTTPException, Request, status
from fastapi.responses import RedirectResponse, Response
from sqlalchemy import select

from lembas.api.deps import Db, RequiredUser, require_permission
from lembas.api.library import PAGE_SIZE, _page
from lembas.api.pages import sidebar_context
from lembas.db.models import Report
from lembas.security import permissions
from lembas.services import reports as reports_service
from lembas.services import sharing
from lembas.services.library import retrieval
from lembas.services.markdown import render_markdown
from lembas.web.templating import render

log = logging.getLogger(__name__)

router = APIRouter(dependencies=[Depends(require_permission("reports.use"))], tags=["reports"])


@router.get("/reports")
async def reports_list(
    request: Request,
    db: Db,
    user: RequiredUser,
    q: str = "",
    page: int = 1,
    shared: bool = False,
):
    """`shared=1` narrows to reports other people have shared with this reader.

    Reports became shareable at the same time as this filter appeared, and the
    two arrived together on purpose: a feed that quietly grew somebody else's
    work with no way to see only theirs is worse than one that never grew.
    """
    if q.strip():
        rows = reports_service.search(
            db, user, q, limit=PAGE_SIZE, vector=await retrieval.embed_query(db, q)
        )
        pager = {"page": 1, "pages": 1, "total": len(rows)}
    else:
        rows, pager = _page(
            db,
            (
                select(Report).where(sharing.only_shared(Report, user))
                if shared
                else reports_service.visible(user)
            ).order_by(Report.created_at.desc()),
            page,
        )
    return render(
        request,
        "reports/index.html",
        {
            "section": "reports",
            "reports": rows,
            "q": q,
            "shared": shared,
            "pager": pager,
            **sidebar_context(db, user),
        },
    )


@router.get("/reports/{report_id}")
async def report_detail(request: Request, db: Db, user: RequiredUser, report_id: str):
    report = reports_service.get(db, report_id, user)
    if report is None:
        raise HTTPException(status.HTTP_404_NOT_FOUND, "That report is not available.")
    # Opening one is what reading it means. Done before rendering so the dot on
    # the way in and the dot on the way back to the list agree -- the poller
    # would otherwise re-announce a report the reader is looking at.
    #
    # Only the owner's own reading counts. `unread` is the owner's dot, and
    # somebody a report was shared with opening it would otherwise clear a
    # notification meant for a person who has not seen it.
    if report.owner_id == user.id:
        reports_service.mark_read(db, report)
    return render(
        request,
        "reports/detail.html",
        {
            "section": "reports",
            "report": report,
            # Model output, through the one path allowed to emit HTML.
            "body_html": render_markdown(report.body),
            "can_share": permissions.has(db, user, "library.share"),
            "is_owner": report.owner_id == user.id,
            "share_kind": "report",
            "share_id": report.id,
            **sidebar_context(db, user),
        },
    )


@router.post("/api/reports/{report_id}/delete")
async def delete_report(db: Db, user: RequiredUser, report_id: str) -> Response:
    # `owned`, not `get`: sharing grants reading, so being able to see a report
    # is not being able to delete it out from under the person who filed it.
    report = reports_service.owned(db, report_id, user)
    if report is None:
        raise HTTPException(status.HTTP_404_NOT_FOUND, "That report is not available.")
    reports_service.delete(db, report)
    return RedirectResponse("/reports", status_code=status.HTTP_303_SEE_OTHER)
