"""FastAPI router for notification endpoints."""

from __future__ import annotations

from typing import Any
from uuid import UUID

from fastapi import APIRouter, HTTPException, Query
from pydantic import BaseModel

from notifications.models import (
    Notification,
    NotificationPreferences,
    UpdatePreferences,
)
from notifications.service import (
    get_notifications,
    mark_all_read,
    mark_read,
)
from notifications.store import (
    get_preferences,
    get_unread_count,
    set_preferences,
)
from errors import AuthorizationError, BusinessLogicError, ConflictError, NotFoundError, ValidationError
from api_core.responses import ApiResponse, PaginatedResponse


class NotificationListResponse(BaseModel):
    """Response model for paginated notification list."""

    items: list[Notification]
    total: int
    unread_count: int
    page: int
    per_page: int


class UnreadCountResponse(BaseModel):
    """Response model for unread count."""

    count: int


class MarkReadResponse(BaseModel):
    """Response model for mark-read operations."""

    success: bool


class MarkAllReadResponse(BaseModel):
    """Response model for mark-all-read operations."""

    updated: int


def NotificationRouter(
    *,
    get_user_id: Any,
    prefix: str = "/notifications",
    tags: list[str] | None = None,
) -> APIRouter:
    """Create a FastAPI router for notification endpoints.

    Args:
        get_user_id: A FastAPI dependency that returns the current user's ID.
            Must be an async or sync callable compatible with ``Depends()``.
        prefix: URL prefix for all routes. Defaults to ``/notifications``.
        tags: OpenAPI tags for the router.

    Returns:
        A configured APIRouter.

    Example::

        from fastapi import Depends, Request

        async def get_current_user_id(request: Request) -> str:
            return request.state.user_id

        router = NotificationRouter(get_user_id=get_current_user_id)
        app.include_router(router)
    """
    from fastapi import Depends

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

    @router.get("", response_model=NotificationListResponse)
    async def list_notifications(
        user_id: str = Depends(get_user_id),
        page: int = Query(1, ge=1, description="Page number"),
        unread_only: bool = Query(False, description="Only return unread notifications"),
    ) -> NotificationListResponse:
        """List notifications for the current user with pagination."""
        result = await get_notifications(user_id, page=page, unread_only=unread_only)
        return NotificationListResponse(**result)

    @router.get("/count", response_model=UnreadCountResponse)
    async def unread_count(
        user_id: str = Depends(get_user_id),
    ) -> UnreadCountResponse:
        """Get the number of unread notifications for the current user."""
        count = await get_unread_count(user_id)
        return UnreadCountResponse(count=count)

    @router.patch("/{notification_id}/read", response_model=MarkReadResponse)
    async def mark_notification_read(
        notification_id: UUID,
        user_id: str = Depends(get_user_id),
    ) -> MarkReadResponse:
        """Mark a single notification as read."""
        success = await mark_read(notification_id)
        if not success:
            raise NotFoundError("Notification not found")
        return MarkReadResponse(success=True)

    @router.post("/read-all", response_model=MarkAllReadResponse)
    async def mark_all_notifications_read(
        user_id: str = Depends(get_user_id),
    ) -> MarkAllReadResponse:
        """Mark all unread notifications as read for the current user."""
        updated = await mark_all_read(user_id)
        return MarkAllReadResponse(updated=updated)

    @router.get("/preferences", response_model=NotificationPreferences)
    async def get_notification_preferences(
        user_id: str = Depends(get_user_id),
    ) -> NotificationPreferences:
        """Get notification preferences for the current user."""
        return await get_preferences(user_id)

    @router.put("/preferences", response_model=NotificationPreferences)
    async def update_notification_preferences(
        body: UpdatePreferences,
        user_id: str = Depends(get_user_id),
    ) -> NotificationPreferences:
        """Update notification preferences for the current user."""
        current = await get_preferences(user_id)

        updated = NotificationPreferences(
            user_id=user_id,
            email_enabled=body.email_enabled if body.email_enabled is not None else current.email_enabled,
            in_app_enabled=body.in_app_enabled if body.in_app_enabled is not None else current.in_app_enabled,
            digest_frequency=body.digest_frequency if body.digest_frequency is not None else current.digest_frequency,
        )

        return await set_preferences(user_id, updated)

    return router
