"""
Notification hooks example.

Sends notifications to users after wallet transactions.
POST hooks - run after successful transactions.
"""

import logging
from decimal import Decimal
from typing import Dict, List

from wallet_utils.hooks import HookContext


logger = logging.getLogger(__name__)


class NotificationService:
    """
    Simple notification service for wallet transactions.
    
    In production, integrate with email service (SendGrid, SES),
    SMS service (Twilio), or push notification service (FCM).
    """
    
    def __init__(self):
        self.sent_notifications: List[Dict] = []  # Track sent notifications
        self.logger = logging.getLogger("wallet.notifications")
    
    def send_notification(
        self,
        user_id: int,
        notification_type: str,
        title: str,
        message: str,
        channels: List[str] = None,
        metadata: dict = None,
    ) -> bool:
        """
        Send notification to user.
        
        Args:
            user_id: Recipient user ID
            notification_type: Type of notification (transaction, alert, etc.)
            title: Notification title
            message: Notification message
            channels: List of channels (email, sms, push)
            metadata: Additional data
            
        Returns:
            True if sent successfully
        """
        if channels is None:
            channels = ["email"]  # Default to email
        
        notification = {
            "user_id": user_id,
            "type": notification_type,
            "title": title,
            "message": message,
            "channels": channels,
            "metadata": metadata or {},
        }
        
        # In production, actually send via services
        # For demo, just log and store
        self.sent_notifications.append(notification)
        self.logger.info(
            f"Notification sent to user {user_id} via {channels}: {title}"
        )
        
        return True
    
    def get_user_notifications(self, user_id: int, limit: int = 50):
        """Get notifications for a user."""
        return [
            notif for notif in self.sent_notifications
            if notif["user_id"] == user_id
        ][-limit:]


# Global notification service
_notification_service = NotificationService()


def send_transaction_notification(context: HookContext) -> None:
    """
    POST hook to send transaction notification to user.
    
    Sends email/SMS/push notification after successful transaction.
    
    Args:
        context: Hook context with transaction details
        
    Example:
        >>> from wallet_utils.hooks import register_hook, HookType
        >>> register_hook(
        ...     name="transaction_notifier",
        ...     hook_type=HookType.POST,
        ...     callback=send_transaction_notification,
        ...     operation="*",  # Notify for all operations
        ...     priority=800,  # Medium priority
        ... )
    """
    operation_names = {
        "add": "credited",
        "deduct": "debited",
        "transfer": "transferred",
    }
    
    operation_name = operation_names.get(context.operation, context.operation)
    
    # Build notification title and message
    if context.operation == "transfer":
        title = f"Points {operation_name}"
        message = (
            f"You have {operation_name} {context.amount} {context.point_type} points "
            f"to user {context.to_user_id}. "
            f"Transaction ID: {context.metadata.get('transaction_id')}"
        )
    else:
        title = f"Points {operation_name}"
        message = (
            f"Your {context.point_type} balance has been {operation_name} by {context.amount}. "
            f"New balance: {context.current_balance}. "
            f"Transaction ID: {context.metadata.get('transaction_id')}"
        )
    
    # Add remarks if present
    if context.remarks:
        message += f"\nNote: {context.remarks}"
    
    # Determine notification channels based on amount
    channels = ["email"]  # Always send email
    if context.amount > Decimal("1000.00"):
        channels.append("sms")  # Also SMS for large amounts
    
    _notification_service.send_notification(
        user_id=context.user_id,
        notification_type="transaction",
        title=title,
        message=message,
        channels=channels,
        metadata={
            "operation": context.operation,
            "point_type": context.point_type,
            "amount": float(context.amount),
            "transaction_id": context.metadata.get("transaction_id"),
        },
    )


def send_low_balance_alert(context: HookContext) -> None:
    """
    POST hook to alert user when balance falls below threshold.
    
    Only sends alert after deductions that bring balance below threshold.
    
    Args:
        context: Hook context with transaction details
        
    Example:
        >>> from wallet_utils.hooks import register_hook, HookType
        >>> register_hook(
        ...     name="low_balance_alerter",
        ...     hook_type=HookType.POST,
        ...     callback=send_low_balance_alert,
        ...     operation="deduct",  # Only for deductions
        ...     priority=750,
        ... )
    """
    # Only check after deductions
    if context.operation != "deduct":
        return
    
    # Define low balance threshold per point type
    thresholds = {
        "cash": Decimal("100.00"),
        "credit_balance": Decimal("50.00"),
        "reward_points": Decimal("10.00"),
    }
    
    threshold = thresholds.get(context.point_type, Decimal("0"))
    
    # Check if balance fell below threshold
    if context.current_balance and context.current_balance < threshold:
        title = "Low Balance Alert"
        message = (
            f"Your {context.point_type} balance is now {context.current_balance}, "
            f"which is below the threshold of {threshold}. "
            f"Consider adding more points to avoid transaction failures."
        )
        
        _notification_service.send_notification(
            user_id=context.user_id,
            notification_type="alert",
            title=title,
            message=message,
            channels=["email", "push"],
            metadata={
                "alert_type": "low_balance",
                "point_type": context.point_type,
                "current_balance": float(context.current_balance),
                "threshold": float(threshold),
            },
        )


def send_large_transaction_alert(context: HookContext) -> None:
    """
    POST hook to alert user about large transactions for security.
    
    Args:
        context: Hook context with transaction details
        
    Example:
        >>> from wallet_utils.hooks import register_hook, HookType
        >>> register_hook(
        ...     name="large_tx_alerter",
        ...     hook_type=HookType.POST,
        ...     callback=send_large_transaction_alert,
        ...     operation="*",
        ...     priority=750,
        ... )
    """
    LARGE_AMOUNT = Decimal("5000.00")
    
    if context.amount >= LARGE_AMOUNT:
        title = "Large Transaction Alert"
        message = (
            f"A large transaction of {context.amount} {context.point_type} was just processed "
            f"on your account ({context.operation}). "
            f"If this wasn't you, please contact support immediately. "
            f"Transaction ID: {context.metadata.get('transaction_id')}"
        )
        
        _notification_service.send_notification(
            user_id=context.user_id,
            notification_type="security_alert",
            title=title,
            message=message,
            channels=["email", "sms", "push"],  # All channels for security
            metadata={
                "alert_type": "large_transaction",
                "operation": context.operation,
                "amount": float(context.amount),
                "transaction_id": context.metadata.get("transaction_id"),
            },
        )


def send_transfer_recipient_notification(context: HookContext) -> None:
    """
    POST hook to notify recipient of incoming transfer.
    
    Args:
        context: Hook context with transaction details
        
    Example:
        >>> from wallet_utils.hooks import register_hook, HookType
        >>> register_hook(
        ...     name="transfer_recipient_notifier",
        ...     hook_type=HookType.POST,
        ...     callback=send_transfer_recipient_notification,
        ...     operation="transfer",  # Only for transfers
        ...     priority=800,
        ... )
    """
    # Only for transfers
    if context.operation != "transfer":
        return
    
    if not context.to_user_id:
        return
    
    title = "Points Received"
    message = (
        f"You have received {context.amount} {context.to_point_type or context.point_type} points "
        f"from user {context.user_id}. "
        f"Transaction ID: {context.metadata.get('transaction_id')}"
    )
    
    if context.remarks:
        message += f"\nNote: {context.remarks}"
    
    _notification_service.send_notification(
        user_id=context.to_user_id,
        notification_type="transaction",
        title=title,
        message=message,
        channels=["email", "push"],
        metadata={
            "operation": "receive_transfer",
            "from_user_id": context.user_id,
            "amount": float(context.amount),
            "transaction_id": context.metadata.get("transaction_id"),
        },
    )


def get_notification_service() -> NotificationService:
    """Get the global notification service instance."""
    return _notification_service
