from __future__ import annotations

from fastapi import APIRouter, Form, Request
from fastapi.responses import JSONResponse, RedirectResponse

from app.core.db.common import CommonSessionLocal
from app.core.security.csrf import get_or_create_csrf_token, validate_csrf
from app.core.security.session_auth import get_current_user
from app.core.templating import templates
from app.modules.alerts.service import ALERT_PRIORITIES, count_unread_alerts, list_my_alerts, mark_alert_read, mark_all_alerts_read
from app.modules.core.rbac.deps import get_user_permissions, get_user_roles

router = APIRouter(prefix="/alerts", tags=["alerts-ui"])


def _redirect_login():
    return RedirectResponse(url="/login", status_code=303)


def _base_ctx(request: Request, db, current_user, **ctx):
    base = {
        "request": request,
        "current_user": current_user,
        "current_user_roles": get_user_roles(db, current_user.id),
        "current_user_permissions": get_user_permissions(db, current_user.id),
        "csrf_token": get_or_create_csrf_token(request),
    }
    base.update(ctx)
    return base


@router.get("/poll")
def poll_unread_alerts(request: Request, limit: int = 5):
    """Lightweight polling endpoint used by the base layout toast popup.

    Returns a small list of unread alerts for the logged-in user. It does not
    mark alerts as read; the normal /alerts page and existing read actions
    continue to control read status.
    """
    db = CommonSessionLocal()
    try:
        current_user = get_current_user(request, db)
        if not current_user:
            return JSONResponse({"authenticated": False, "unread_count": 0, "alerts": []}, status_code=401)

        safe_limit = max(1, min(int(limit or 5), 10))
        rows = list_my_alerts(db, current_user, status="unread", priority="all", limit=safe_limit)
        payload = []
        for row in rows:
            created_at = getattr(row, "created_at_utc", None)
            payload.append(
                {
                    "id": row.id,
                    "title": row.title or "Alert",
                    "message": row.message or "",
                    "priority": row.priority or "normal",
                    "alert_type": row.alert_type or "general",
                    "target_url": row.target_url or "/alerts",
                    "created_at_utc": created_at.isoformat() if created_at else None,
                }
            )

        return JSONResponse(
            {
                "authenticated": True,
                "unread_count": count_unread_alerts(db, current_user),
                "alerts": payload,
            }
        )
    finally:
        db.close()


@router.get("")
def alerts_list(request: Request, status: str = "all", priority: str = "all"):
    db = CommonSessionLocal()
    try:
        current_user = get_current_user(request, db)
        if not current_user:
            return _redirect_login()
        status = status if status in {"all", "unread", "read"} else "all"
        priority = priority if priority in ALERT_PRIORITIES else "all"
        rows = list_my_alerts(db, current_user, status=status, priority=priority, limit=150)
        return templates.TemplateResponse(
            "modules/alerts/templates/alerts/list.html",
            _base_ctx(
                request,
                db,
                current_user,
                title="My Alerts",
                alerts=rows,
                status=status,
                priority=priority,
                priorities=ALERT_PRIORITIES,
                unread_count=count_unread_alerts(db, current_user),
            ),
        )
    finally:
        db.close()


@router.post("/{alert_id}/read")
def mark_read(request: Request, alert_id: int, csrf_token: str = Form(...)):
    db = CommonSessionLocal()
    try:
        current_user = get_current_user(request, db)
        if not current_user:
            return _redirect_login()
        validate_csrf(request, csrf_token)
        mark_alert_read(db, current_user, alert_id)
        return RedirectResponse(url="/alerts", status_code=303)
    finally:
        db.close()


@router.post("/read-all")
def mark_all_read(request: Request, csrf_token: str = Form(...)):
    db = CommonSessionLocal()
    try:
        current_user = get_current_user(request, db)
        if not current_user:
            return _redirect_login()
        validate_csrf(request, csrf_token)
        mark_all_alerts_read(db, current_user)
        return RedirectResponse(url="/alerts", status_code=303)
    finally:
        db.close()
