"""
Daily transaction limit hook example.

This hook prevents users from exceeding daily transaction limits.
It tracks cumulative transactions per day and rejects when limit is exceeded.
"""

from datetime import datetime, timedelta
from decimal import Decimal
from typing import Dict

from wallet_utils.hooks import HookContext
from wallet_utils.exceptions import HookRejectionError


class DailyLimitTracker:
    """
    In-memory tracker for daily transaction limits.
    
    In production, replace this with Redis or database storage.
    """
    
    def __init__(self):
        # Format: {(user_id, point_type, date): total_amount}
        self._limits: Dict[tuple, Decimal] = {}
        self._max_daily_limit = Decimal("5000.00")  # Default limit
        self._user_limits: Dict[int, Decimal] = {}  # Per-user overrides
    
    def set_user_limit(self, user_id: int, limit: Decimal) -> None:
        """Set custom limit for specific user."""
        self._user_limits[user_id] = limit
    
    def get_user_limit(self, user_id: int) -> Decimal:
        """Get limit for user (custom or default)."""
        return self._user_limits.get(user_id, self._max_daily_limit)
    
    def get_today_total(self, user_id: int, point_type: str) -> Decimal:
        """Get total amount transacted today for user and point type."""
        today = datetime.now().date()
        key = (user_id, point_type, today)
        return self._limits.get(key, Decimal("0"))
    
    def add_transaction(self, user_id: int, point_type: str, amount: Decimal) -> None:
        """Record a transaction."""
        today = datetime.now().date()
        key = (user_id, point_type, today)
        current = self._limits.get(key, Decimal("0"))
        self._limits[key] = current + amount
    
    def cleanup_old_data(self, days: int = 7) -> None:
        """Remove data older than specified days."""
        cutoff = datetime.now().date() - timedelta(days=days)
        keys_to_remove = [
            key for key in self._limits.keys()
            if key[2] < cutoff
        ]
        for key in keys_to_remove:
            del self._limits[key]


# Global tracker instance
_tracker = DailyLimitTracker()


def check_daily_limit(context: HookContext) -> bool:
    """
    PRE hook to check if transaction would exceed daily limit.
    
    Args:
        context: Hook context with transaction details
        
    Returns:
        True if within limit, raises HookRejectionError if limit exceeded
        
    Raises:
        HookRejectionError: When daily limit would be exceeded
        
    Example:
        >>> from wallet_utils.hooks import register_hook, HookType
        >>> register_hook(
        ...     name="daily_limit_checker",
        ...     hook_type=HookType.PRE,
        ...     callback=check_daily_limit,
        ...     operation="deduct",  # Apply only to deductions
        ...     priority=50,  # High priority security check
        ... )
    """
    # Only check for deductions and transfers (not adds)
    if context.operation == "add":
        return True
    
    user_id = context.user_id
    point_type = context.point_type
    amount = context.amount
    
    # Get current daily total
    today_total = _tracker.get_today_total(user_id, point_type)
    user_limit = _tracker.get_user_limit(user_id)
    
    # Check if adding this transaction would exceed limit
    new_total = today_total + amount
    
    if new_total > user_limit:
        raise HookRejectionError(
            error_code="DAILY_LIMIT_EXCEEDED",
            message=f"Daily transaction limit exceeded for {point_type}",
            details={
                "limit": float(user_limit),
                "today_total": float(today_total),
                "requested": float(amount),
                "would_be": float(new_total),
                "remaining": float(user_limit - today_total),
            }
        )
    
    # Store in metadata for POST hook to record
    context.metadata["daily_limit_check_passed"] = True
    context.metadata["today_total_before"] = today_total
    
    return True


def record_daily_transaction(context: HookContext) -> None:
    """
    POST hook to record transaction in daily limit tracker.
    
    Should be registered alongside check_daily_limit to track successful transactions.
    
    Args:
        context: Hook context with transaction details
        
    Example:
        >>> from wallet_utils.hooks import register_hook, HookType
        >>> register_hook(
        ...     name="daily_limit_recorder",
        ...     hook_type=HookType.POST,
        ...     callback=record_daily_transaction,
        ...     operation="deduct",
        ...     priority=100,
        ... )
    """
    # Only record deductions and transfers
    if context.operation == "add":
        return
    
    # Only record if PRE check passed
    if not context.metadata.get("daily_limit_check_passed"):
        return
    
    _tracker.add_transaction(context.user_id, context.point_type, context.amount)


def get_tracker() -> DailyLimitTracker:
    """Get the global daily limit tracker instance."""
    return _tracker


# Example: Set custom limit for VIP users
def set_vip_user_limit(user_id: int, limit: Decimal = Decimal("10000.00")) -> None:
    """Set higher daily limit for VIP users."""
    _tracker.set_user_limit(user_id, limit)
