"""
Role Permissions Celery Tasks — PRD-008 RBAC Multi-User Merchant Accounts.

Covers:
  - Sending invite emails to new team members.

Beat schedule registration is in src/worker/config.py.
"""

import logging
from typing import Any, Dict

from celery.utils.log import get_task_logger
from src.worker.celery_app import celery_app

logger = get_task_logger(__name__)


@celery_app.task(
    bind=True,
    name="role_permissions.send_invite_email",
    max_retries=3,
    default_retry_delay=60,
)
def send_invite_email(self, invite_id: int, raw_token: str) -> Dict[str, Any]:
    """
    Send a branded invite email to the recipient.

    Loads the invite, merchant branding, and inviter details from the DB,
    then dispatches the transactional email.

    Args:
        invite_id:  Primary key of the MerchantInvite row.
        raw_token:  Plain-text invite token (NOT the hash).
                    Must be embedded in the accept link.

    Returns:
        dict with task_id and delivery status.
    """
    try:
        from src.core.database import SessionCelery
        from src.core.config import settings

        with SessionCelery() as db:
            from sqlalchemy import select

            from src.apps.role_permissions.models.merchant_invite import MerchantInvite
            from src.apps.merchants.models.merchant import Merchant
            from src.apps.merchants.models.merchant_settings import MerchantSettings

            invite = db.execute(
                select(MerchantInvite).where(MerchantInvite.id == invite_id)
            ).scalar_one_or_none()

            if not invite:
                logger.warning("send_invite_email: invite %s not found", invite_id)
                return {"task_id": self.request.id, "status": "not_found", "invite_id": invite_id}

            if not invite.is_pending:
                logger.info(
                    "send_invite_email: invite %s is no longer pending, skipping",
                    invite_id,
                )
                return {"task_id": self.request.id, "status": "skipped", "invite_id": invite_id}

            merchant = db.execute(
                select(Merchant).where(
                    Merchant.id == invite.merchant_id,
                    Merchant.deleted_at.is_(None),
                )
            ).scalar_one_or_none()

            merchant_name = merchant.name if merchant else "HubWallet"

            # Fetch logo from branding settings
            logo_url = None
            if merchant and merchant.brand_logo:
                logo_url = (
                    f"{settings.SERVER_HOST}/api/v1/files/download"
                    f"?filepath=/uploads/{merchant.merchant_id}/{merchant.brand_logo.name}"
                )

            # Build accept URL
            front_url = getattr(settings, "SERVER_FRONT", "http://localhost:3000")
            accept_url = f"{front_url}/accept-invite?token={raw_token}"

            inviter = invite.inviter
            inviter_name = (
                f"{inviter.first_name or ''} {inviter.last_name or ''}".strip()
                if inviter
                else merchant_name
            )

            role_name = invite.role.label if invite.role else "Team Member"

            logger.info(
                "Sending invite email to %s (merchant: %s, role: %s)",
                invite.email,
                merchant_name,
                role_name,
            )

            # TODO: Replace the stub below with a real email-service call, e.g.:
            #   from src.core.email import send_transactional_email
            #   send_transactional_email(
            #       to=invite.email,
            #       template="team_invite",
            #       context={
            #           "merchant_name": merchant_name,
            #           "logo_url": logo_url,
            #           "inviter_name": inviter_name,
            #           "role_name": role_name,
            #           "accept_url": accept_url,
            #           "expires_at": invite.expires_at.isoformat(),
            #       },
            #   )

            # SECURITY: Do NOT log accept_url — it contains the raw invite token.
            # Logging the URL would expose a one-time credential to log aggregators.
            logger.info(
                "Invite email stub sent to %s (invite_id=%s)",
                invite.email,
                invite_id,
            )

        return {
            "task_id": self.request.id,
            "status": "sent_stub",
            "recipient": invite.email,
            "invite_id": invite_id,
        }

    except Exception as exc:
        logger.error("send_invite_email failed for invite %s: %s", invite_id, exc)
        raise self.retry(exc=exc)


__all__ = ["send_invite_email"]
