# app/modules/loyalty/tasks/wallet_sync.py
"""
Wallet synchronization task.

Handles syncing loyalty card data to Google Wallet and Apple Wallet
for cards that may have missed real-time updates.
"""

import logging

from celery import shared_task

logger = logging.getLogger(__name__)


@shared_task(name="loyalty.sync_wallet_passes")
def sync_wallet_passes() -> dict:
    """
    Sync wallet passes for cards that may be out of sync.

    This catches any cards that missed real-time updates due to
    errors or network issues.

    Returns:
        Summary of synced passes
    """
    from datetime import UTC, datetime, timedelta

    from app.core.database import SessionLocal
    from app.modules.loyalty.models import LoyaltyCard, LoyaltyTransaction
    from app.modules.loyalty.services import wallet_service

    db = SessionLocal()
    try:
        # Find cards with transactions in the last hour that have wallet IDs
        one_hour_ago = datetime.now(UTC) - timedelta(hours=1)

        # Get card IDs with recent transactions
        recent_tx_card_ids = (
            db.query(LoyaltyTransaction.card_id)
            .filter(LoyaltyTransaction.transaction_at >= one_hour_ago)
            .distinct()
            .all()
        )
        card_ids = [row[0] for row in recent_tx_card_ids]

        if not card_ids:
            logger.info("No cards with recent transactions to sync")
            return {
                "status": "success",
                "cards_checked": 0,
                "google_synced": 0,
                "apple_synced": 0,
            }

        # Get cards with wallet integrations
        cards = (
            db.query(LoyaltyCard)
            .filter(
                LoyaltyCard.id.in_(card_ids),
                (LoyaltyCard.google_object_id.isnot(None))
                | (LoyaltyCard.apple_serial_number.isnot(None)),
            )
            .all()
        )

        google_synced = 0
        apple_synced = 0
        failed_card_ids = []

        for card in cards:
            synced = False
            for attempt in range(2):  # 1 retry
                try:
                    results = wallet_service.sync_card_to_wallets(db, card)
                    if results.get("google_wallet"):
                        google_synced += 1
                    if results.get("apple_wallet"):
                        apple_synced += 1
                    synced = True
                    break
                except Exception as e:
                    if attempt == 0:
                        logger.warning(
                            f"Failed to sync card {card.id} (attempt 1/2), "
                            f"retrying in 2s: {e}"
                        )
                        import time
                        time.sleep(2)
                    else:
                        logger.error(
                            f"Failed to sync card {card.id} after 2 attempts: {e}"
                        )
            if not synced:
                failed_card_ids.append(card.id)

        logger.info(
            f"Wallet sync complete: {len(cards)} cards checked, "
            f"{google_synced} Google, {apple_synced} Apple, "
            f"{len(failed_card_ids)} failed"
        )

        return {
            "status": "success",
            "cards_checked": len(cards),
            "google_synced": google_synced,
            "apple_synced": apple_synced,
            "failed_card_ids": failed_card_ids,
        }

    except Exception as e:
        logger.error(f"Wallet sync task failed: {e}")
        return {
            "status": "error",
            "error": str(e),
        }
    finally:
        db.close()
