import logging
from datetime import timedelta

from django.utils import timezone

from apps.masterdata.platform_setting import PlatformSetting
from ..models import BankAccount, BankAccountOTP

logger = logging.getLogger("withdrawals")

OTP_EXPIRY_MINUTES = 10


def send_bank_account_otp(bank_account: BankAccount) -> dict:
    """Generate and send OTP for bank account verification."""
    # Invalidate any existing unused OTPs for this bank account
    BankAccountOTP.objects.filter(bank_account=bank_account, is_used=False).update(is_used=True)

    otp_code = BankAccountOTP.generate_code()
    expires_at = timezone.now() + timedelta(minutes=OTP_EXPIRY_MINUTES)
    otp_record = BankAccountOTP.objects.create(
        bank_account=bank_account,
        otp_code=otp_code,
        expires_at=expires_at,
    )

    channel = PlatformSetting.get_value("withdrawal_otp_channel", "sms").lower()
    user = bank_account.user

    _deliver_otp(channel, user, otp_code)
    logger.info({
        "event": "bank_account_otp_sent",
        "user": user.id,
        "bank_account": str(bank_account.id),
        "channel": channel,
    })
    return {"otp_id": otp_record.id, "channel": channel, "expires_minutes": OTP_EXPIRY_MINUTES}


def verify_bank_account_otp(bank_account: BankAccount, otp_code: str) -> bool:
    """Verify OTP and mark bank account as verified if correct."""
    otp = (
        BankAccountOTP.objects.filter(bank_account=bank_account, is_used=False)
        .order_by("-created_at")
        .first()
    )
    if not otp or not otp.is_valid():
        return False
    if otp.otp_code != str(otp_code).strip():
        return False

    otp.is_used = True
    otp.save(update_fields=["is_used"])

    bank_account.is_verified = True
    bank_account.save(update_fields=["is_verified"])
    logger.info({
        "event": "bank_account_verified",
        "user": bank_account.user.id,
        "bank_account": str(bank_account.id),
    })
    return True


def _deliver_otp(channel: str, user, otp_code: str):
    """Deliver OTP via the configured channel (SMS / WhatsApp / Email)."""
    message = f"Your TrueWave bank account verification OTP is: {otp_code}. Valid for {OTP_EXPIRY_MINUTES} minutes."
    try:
        if channel == "whatsapp":
            from apps.notifications.whatsapp_service import send_whatsapp_message
            mobile = getattr(user, "mobile", None) or getattr(user, "phone_number", None) or ""
            if mobile:
                send_whatsapp_message(recipient=str(mobile), message_type="text", text=message)
        elif channel == "email":
            from apps.notifications.email_delivery import send_email_using_active_config
            email = getattr(user, "email", None) or ""
            if email:
                send_email_using_active_config(
                    subject="Bank Account Verification OTP",
                    message=message,
                    recipient_list=[email],
                    purpose="otp",
                )
        else:
            # Default: SMS via Celery task
            from apps.notifications.tasks import send_sms_task
            mobile = getattr(user, "mobile", None) or getattr(user, "phone_number", None) or ""
            if mobile:
                send_sms_task.delay(str(mobile), message)
    except Exception as exc:
        logger.warning({"event": "otp_delivery_failed", "channel": channel, "user": user.id, "error": str(exc)})
        # OTP is still created; log it for development
    logger.debug({"event": "otp_code_debug", "otp": otp_code, "channel": channel})
