# retoor <retoor@molodetz.nl>

import logging
from datetime import datetime, timedelta, timezone
from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse, JSONResponse
from devplacepy.database import get_table, db
from devplacepy.templating import (
    clear_unread_cache,
    jinja_unread_count,
    jinja_unread_messages,
)
from devplacepy.utils import require_user, get_current_user, time_ago
from devplacepy.seo import base_seo_context
from devplacepy.responses import respond, action_result
from devplacepy.schemas import NotificationsOut
from devplacepy.services.audit import record as audit

logger = logging.getLogger(__name__)
router = APIRouter()

PAGE_SIZE = 25


def _group_label(created_at: str) -> str:
    try:
        dt = datetime.fromisoformat(created_at)
        now = datetime.now(timezone.utc)
        today = now.date()
        date = dt.date()
        if date == today:
            return "Today"
        if date == today - timedelta(days=1):
            return "Yesterday"
        if (today - date).days < 7:
            return "This week"
        return "Older"
    except Exception:
        return "Older"


@router.get("", response_class=HTMLResponse)
async def notifications_page(request: Request, before: str = None):
    user = require_user(request)

    next_cursor = None
    try:
        notifications_table = get_table("notifications")
        filters = {"user_uid": user["uid"]}
        if before:
            filters["created_at"] = {"<": before}
        raw_notifications = list(
            notifications_table.find(
                **filters, order_by=["-created_at"], _limit=PAGE_SIZE + 1
            )
        )

        has_more = len(raw_notifications) > PAGE_SIZE
        raw_notifications = raw_notifications[:PAGE_SIZE]
        if has_more and raw_notifications:
            next_cursor = raw_notifications[-1]["created_at"]

        enriched = []
        if raw_notifications:
            from devplacepy.database import get_users_by_uids

            actor_uids = [
                n.get("related_uid") for n in raw_notifications if n.get("related_uid")
            ]
            actors = get_users_by_uids(actor_uids)
        else:
            actors = {}
        for n in raw_notifications:
            enriched.append(
                {
                    "notification": n,
                    "actor": actors.get(n.get("related_uid")),
                    "time_ago": time_ago(n["created_at"]),
                }
            )

        groups = []
        current_label = None
        current_entries = []
        for item in enriched:
            label = _group_label(item["notification"]["created_at"])
            if label != current_label:
                if current_entries:
                    groups.append({"label": current_label, "entries": current_entries})
                current_label = label
                current_entries = []
            current_entries.append(item)
        if current_entries:
            groups.append({"label": current_label, "entries": current_entries})
    except Exception as e:
        logger.exception(f"Error loading notifications: {e}")
        groups = []

    seo_ctx = base_seo_context(
        request,
        title="Notifications",
        robots="noindex,nofollow",
        breadcrumbs=[
            {"name": "Home", "url": "/feed"},
            {"name": "Notifications", "url": "/notifications"},
        ],
    )
    return respond(
        request,
        "notifications.html",
        {
            **seo_ctx,
            "request": request,
            "user": user,
            "notification_groups": groups,
            "next_cursor": next_cursor,
        },
        model=NotificationsOut,
    )


@router.get("/counts")
async def unread_counts(request: Request):
    user = get_current_user(request)
    if not user:
        return JSONResponse({"notifications": 0, "messages": 0})
    return JSONResponse(
        {
            "notifications": jinja_unread_count(user["uid"]),
            "messages": jinja_unread_messages(user["uid"]),
        }
    )


@router.get("/open/{notification_uid}")
async def open_notification(request: Request, notification_uid: str):
    user = require_user(request)
    notifications_table = get_table("notifications")
    n = notifications_table.find_one(uid=notification_uid)
    if not n or n["user_uid"] != user["uid"]:
        return action_result(request, "/notifications")
    if not n["read"]:
        notifications_table.update({"id": n["id"], "read": True}, ["id"])
        clear_unread_cache(user["uid"])
    audit.record(
        request,
        "notification.open",
        user=user,
        target_type="notification",
        target_uid=notification_uid,
        summary=f"{user['username']} opened a notification",
        links=[audit.target("notification", notification_uid)],
    )
    return action_result(request, n.get("target_url") or "/notifications")


@router.post("/mark-read/{notification_uid}")
async def mark_read(request: Request, notification_uid: str):
    user = require_user(request)
    notifications_table = get_table("notifications")
    n = notifications_table.find_one(uid=notification_uid)
    if n and n["user_uid"] == user["uid"]:
        notifications_table.update({"id": n["id"], "read": True}, ["id"])
        clear_unread_cache(user["uid"])
        audit.record(
            request,
            "notification.read.one",
            user=user,
            target_type="notification",
            target_uid=notification_uid,
            summary=f"{user['username']} marked a notification read",
            links=[audit.target("notification", notification_uid)],
        )
    return action_result(request, "/notifications")


@router.post("/mark-all-read")
async def mark_all_read(request: Request):
    user = require_user(request)
    with db:
        db.query(
            "UPDATE notifications SET read = 1 WHERE user_uid = :u AND read = 0",
            u=user["uid"],
        )
    clear_unread_cache(user["uid"])
    audit.record(
        request,
        "notification.read.all",
        user=user,
        summary=f"{user['username']} marked all notifications read",
    )
    return action_result(request, "/notifications")
