"""High-level notification service for business logic orchestration."""

from __future__ import annotations

import uuid

from notifications.config import get_config
from notifications.models import (
    CreateNotification,
    Notification,
    NotificationType,
)
from notifications.store import (
    get_by_user,
    get_total_count,
    get_unread_count,
    insert,
    insert_bulk,
)
from notifications.store import mark_all_read as store_mark_all_read
from notifications.store import mark_read as store_mark_read
from errors import NotFoundError, ValidationError


async def send_notification(
    user_id: str,
    type: NotificationType | str,
    title: str,
    message: str,
    action_url: str | None = None,
) -> Notification:
    """Create and store a single notification for a user.

    Args:
        user_id: The target user's ID.
        type: Notification type (info, success, warning, error).
        title: Short notification title.
        message: Notification body.
        action_url: Optional URL the notification links to.

    Returns:
        The created Notification.
    """
    notification_type = NotificationType(type) if isinstance(type, str) else type

    return await insert(
        CreateNotification(
            user_id=user_id,
            type=notification_type,
            title=title,
            message=message,
            action_url=action_url,
        )
    )


async def send_bulk(
    user_ids: list[str],
    type: NotificationType | str,
    title: str,
    message: str,
    action_url: str | None = None,
) -> list[Notification]:
    """Create the same notification for multiple users in a single transaction.

    Args:
        user_ids: List of target user IDs.
        type: Notification type.
        title: Short notification title.
        message: Notification body.
        action_url: Optional URL the notification links to.

    Returns:
        List of created Notifications.
    """
    notification_type = NotificationType(type) if isinstance(type, str) else type

    payloads = [
        CreateNotification(
            user_id=uid,
            type=notification_type,
            title=title,
            message=message,
            action_url=action_url,
        )
        for uid in user_ids
    ]

    return await insert_bulk(payloads)


async def get_notifications(
    user_id: str,
    page: int = 1,
    unread_only: bool = False,
) -> dict:
    """Fetch a paginated list of notifications for a user.

    Args:
        user_id: The user to fetch notifications for.
        page: Page number (1-indexed).
        unread_only: If True, only return unread notifications.

    Returns:
        Dictionary with keys: items, total, unread_count, page, per_page.
    """
    config = get_config()
    per_page = config.max_per_page
    offset = (max(1, page) - 1) * per_page

    items = await get_by_user(user_id, limit=per_page, offset=offset, unread_only=unread_only)
    total = await get_total_count(user_id, unread_only=unread_only)
    unread_count = await get_unread_count(user_id)

    return {
        "items": items,
        "total": total,
        "unread_count": unread_count,
        "page": page,
        "per_page": per_page,
    }


async def mark_read(notification_id: str | uuid.UUID) -> bool:
    """Mark a single notification as read.

    Args:
        notification_id: The notification ID (string or UUID).

    Returns:
        True if the notification was found and updated, False otherwise.
    """
    nid = uuid.UUID(notification_id) if isinstance(notification_id, str) else notification_id
    return await store_mark_read(nid)


async def mark_all_read(user_id: str) -> int:
    """Mark all unread notifications for a user as read.

    Args:
        user_id: The user whose notifications should be marked read.

    Returns:
        The number of notifications that were updated.
    """
    return await store_mark_all_read(user_id)
