# app/modules/loyalty/services/notification_service.py
"""
Loyalty notification service.

Thin wrapper that resolves customer/card/program data into template
variables and dispatches emails asynchronously via the Celery task.
"""

import logging

from sqlalchemy.orm import Session

from app.modules.loyalty.models import LoyaltyCard

logger = logging.getLogger(__name__)


class LoyaltyNotificationService:
    """Dispatches loyalty email notifications."""

    def _resolve_context(self, db: Session, card: LoyaltyCard) -> dict | None:
        """Load customer, store, and program info for a card.

        Returns None if the customer has no email (can't send).
        """
        from app.modules.customers.services.customer_service import customer_service
        from app.modules.tenancy.services.store_service import store_service

        customer = customer_service.get_customer_by_id(db, card.customer_id)
        if not customer or not customer.email:
            return None

        store = store_service.get_store_by_id_optional(db, card.enrolled_at_store_id)
        program = card.program

        return {
            "customer": customer,
            "store": store,
            "program": program,
            "to_email": customer.email,
            "to_name": customer.full_name,
            "store_id": card.enrolled_at_store_id,
            "customer_id": customer.id,
            "customer_name": customer.full_name,
            "program_name": program.display_name if program else "Loyalty Program",
            "store_name": store.name if store else "",
        }

    def _dispatch(
        self, template_code: str, ctx: dict, extra_vars: dict | None = None
    ):
        """Enqueue a notification email via Celery."""
        from app.modules.loyalty.tasks.notifications import send_notification_email

        variables = {
            "customer_name": ctx["customer_name"],
            "program_name": ctx["program_name"],
            "store_name": ctx["store_name"],
        }
        if extra_vars:
            variables.update(extra_vars)

        send_notification_email.delay(
            template_code=template_code,
            to_email=ctx["to_email"],
            to_name=ctx["to_name"],
            variables=variables,
            store_id=ctx["store_id"],
            customer_id=ctx["customer_id"],
        )
        logger.info(
            f"Queued {template_code} for {ctx['to_email']}"
        )

    def send_enrollment_confirmation(self, db: Session, card: LoyaltyCard):
        """Send enrollment confirmation email."""
        ctx = self._resolve_context(db, card)
        if not ctx:
            return
        self._dispatch("loyalty_enrollment", ctx, {
            "card_number": card.card_number,
        })

    def send_welcome_bonus(self, db: Session, card: LoyaltyCard, points: int):
        """Send welcome bonus notification (only if points > 0)."""
        if points <= 0:
            return
        ctx = self._resolve_context(db, card)
        if not ctx:
            return
        self._dispatch("loyalty_welcome_bonus", ctx, {
            "points": str(points),
        })

    def send_points_expiration_warning(
        self,
        db: Session,
        card: LoyaltyCard,
        expiring_points: int,
        days_remaining: int,
        expiration_date: str,
    ):
        """Send points expiring warning email."""
        ctx = self._resolve_context(db, card)
        if not ctx:
            return
        self._dispatch("loyalty_points_expiring", ctx, {
            "points": str(expiring_points),
            "days_remaining": str(days_remaining),
            "expiration_date": expiration_date,
        })

    def send_points_expired(
        self, db: Session, card: LoyaltyCard, expired_points: int
    ):
        """Send points expired notification email."""
        ctx = self._resolve_context(db, card)
        if not ctx:
            return
        self._dispatch("loyalty_points_expired", ctx, {
            "expired_points": str(expired_points),
        })

    def send_reward_available(
        self, db: Session, card: LoyaltyCard, reward_name: str
    ):
        """Send reward earned notification email."""
        ctx = self._resolve_context(db, card)
        if not ctx:
            return
        self._dispatch("loyalty_reward_ready", ctx, {
            "reward_name": reward_name,
        })


# Singleton
notification_service = LoyaltyNotificationService()
