"""Notification API endpoints."""

import uuid
from datetime import datetime

from fastapi import APIRouter, Depends, HTTPException, Query, status
from pydantic import BaseModel, ConfigDict, Field
from sqlalchemy.ext.asyncio import AsyncSession

from src.auth.dependencies import get_current_user, get_db_session
from src.models.user import User
from src.models import UserConfig
from src.services.shared.notification_service import notification_service

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


class NotificationItem(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: uuid.UUID
    user_id: uuid.UUID
    category: str
    severity: str
    title: str
    message: str | None
    source_type: str | None
    source_id: uuid.UUID | None
    notification_metadata: dict = Field(serialization_alias="metadata")
    read_at: datetime | None
    dismissed_at: datetime | None
    created_at: datetime


class NotificationListResponse(BaseModel):
    items: list[NotificationItem]
    total: int
    limit: int
    offset: int


class UnreadCountResponse(BaseModel):
    count: int


class MarkAllReadResponse(BaseModel):
    marked_count: int


class ClearAllResponse(BaseModel):
    cleared_count: int


async def _get_mute_categories(
    session: AsyncSession,
    user_id: uuid.UUID,
) -> list[str]:
    """Read notification mute categories from user config."""
    from sqlalchemy import select

    result = await session.execute(
        select(UserConfig).where(UserConfig.user_id == user_id)
    )
    config = result.scalar_one_or_none()
    if config is None:
        return []
    mute_categories = config.config.get("notification_mute_categories", [])
    if isinstance(mute_categories, list):
        return mute_categories
    return []


@router.get("", response_model=NotificationListResponse)
async def list_notifications(
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    unread_only: bool = Query(False),
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_db_session),
) -> NotificationListResponse:
    """List notifications for the authenticated user."""
    mute_categories = await _get_mute_categories(session, user.id)
    items, total = await notification_service.list_notifications(
        session,
        user.id,
        limit=limit,
        offset=offset,
        unread_only=unread_only,
        mute_categories=mute_categories,
    )
    return NotificationListResponse(
        items=[NotificationItem.model_validate(item) for item in items],
        total=total,
        limit=limit,
        offset=offset,
    )


@router.get("/unread", response_model=UnreadCountResponse)
async def get_unread_count(
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_db_session),
) -> UnreadCountResponse:
    """Get unread notification count for the authenticated user."""
    count = await notification_service.get_unread_count(session, user.id)
    return UnreadCountResponse(count=count)


@router.patch("/{notification_id}/read", response_model=NotificationItem)
async def mark_notification_read(
    notification_id: uuid.UUID,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_db_session),
) -> NotificationItem:
    """Mark a single notification as read."""
    try:
        notification = await notification_service.mark_read(
            session, notification_id, user.id
        )
    except ValueError as exc:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Notification not found",
        ) from exc
    return NotificationItem.model_validate(notification)


@router.post("/mark-all-read", response_model=MarkAllReadResponse)
async def mark_all_read(
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_db_session),
) -> MarkAllReadResponse:
    """Mark all unread notifications as read."""
    marked = await notification_service.mark_all_read(session, user.id)
    return MarkAllReadResponse(marked_count=marked)


@router.delete("", status_code=status.HTTP_200_OK)
async def clear_all_notifications(
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_db_session),
) -> ClearAllResponse:
    """Dismiss all notifications for the authenticated user."""
    cleared = await notification_service.dismiss_all(session, user.id)
    return ClearAllResponse(cleared_count=cleared)


@router.delete("/{notification_id}", status_code=status.HTTP_204_NO_CONTENT)
async def dismiss_notification(
    notification_id: uuid.UUID,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_db_session),
) -> None:
    """Soft-delete (dismiss) a single notification."""
    try:
        await notification_service.dismiss(session, notification_id, user.id)
    except ValueError as exc:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Notification not found",
        ) from exc
