import json
import logging
import os

from pywebpush import webpush, WebPushException

from db.push_subscriptions import get_subscriptions_by_user, delete_subscription_by_id

logger = logging.getLogger(__name__)


def _get_vapid_private_key() -> str | None:
    return os.environ.get('VAPID_PRIVATE_KEY')


def _get_vapid_claims_email() -> str:
    return os.environ.get('VAPID_CLAIMS_EMAIL', 'admin@reward-app.local')


def send_push_to_user(user_id: str, payload: dict) -> int:
    """
    Send a web push notification to all stored subscriptions for the user.
    Returns the number of subscriptions successfully notified.

    Stale/expired subscriptions (HTTP 404/410) are removed automatically.
    """
    private_key = _get_vapid_private_key()
    if not private_key:
        logger.warning('VAPID_PRIVATE_KEY not configured; skipping push notification')
        return 0

    subscriptions = get_subscriptions_by_user(user_id)
    if not subscriptions:
        return 0

    claims_email = _get_vapid_claims_email()
    sent = 0

    for sub in subscriptions:
        try:
            subscription_info = {
                'endpoint': sub.endpoint,
                'keys': sub.keys,
            }
            webpush(
                subscription_info=subscription_info,
                data=json.dumps(payload),
                vapid_private_key=private_key,
                vapid_claims={'sub': f'mailto:{claims_email}'},
                ttl=86400,
            )
            sent += 1
        except WebPushException as e:
            status_code = e.response.status_code if e.response is not None else None
            if status_code in (404, 410):
                # Subscription is gone — clean it up
                logger.info(
                    f'Removing stale push subscription {sub.id} for user {user_id} (HTTP {status_code})'
                )
                delete_subscription_by_id(sub.id)
            elif status_code == 403 and 'VAPID credentials' in str(e):
                # The subscription was created with a different VAPID keypair.
                # Remove it so the client can register a fresh subscription next time.
                logger.info(
                    f'Removing VAPID-mismatched subscription {sub.id} for user {user_id} (HTTP 403)'
                )
                delete_subscription_by_id(sub.id)
            else:
                logger.error(
                    f'WebPushException for subscription {sub.id} (user {user_id}): {e}'
                )
        except Exception as e:
            logger.error(f'Unexpected error sending push to subscription {sub.id}: {e}')

    return sent
