from celery import shared_task
from celery.utils.log import get_task_logger
from django.core.mail import send_mail
from django.conf import settings
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes
from django.template.loader import render_to_string
from .tokens import *
from .models import CustomUser

logger = get_task_logger(__name__)

def send_email_with_context(recipients, subject, message=None, template_name=None, html_template_name=None, context=None):
    """
    General function to send emails with a specific context.
    Supports rendering plain text and HTML templates.
    Converts `user` in context to a plain dict to avoid template access to the model.
    """
    if isinstance(recipients, str):
        recipients = [recipients]

    html_message = None
    if template_name or html_template_name:
        # Best effort to resolve both templates if only one provided
        if not template_name and html_template_name:
            template_name = html_template_name.replace(".html", ".txt")
        if not html_template_name and template_name:
            html_template_name = template_name.replace(".txt", ".html")

        ctx = dict(context or {})
        # Sanitize user if someone passes the model by mistake
        if "user" in ctx and not isinstance(ctx["user"], dict):
            try:
                ctx["user"] = _build_user_template_ctx(ctx["user"])
            except Exception:
                ctx["user"] = {}

        message = render_to_string(template_name, ctx)
        html_message = render_to_string(html_template_name, ctx)

    try:
        send_mail(
            subject=subject,
            message=message or "",
            from_email=None,
            recipient_list=recipients,
            fail_silently=False,
            html_message=html_message,
        )
        if settings.EMAIL_BACKEND == 'django.core.mail.backends.console.EmailBackend':
            logger.debug(f"\nEMAIL OBSAH:\n{message}\nKONEC OBSAHU")
        return True
    except Exception as e:
        logger.error(f"E-mail se neodeslal: {e}")
        return False


def _build_user_template_ctx(user: CustomUser) -> dict:
    """
    Return a plain dict for templates instead of passing the DB model.
    Provides aliases to avoid template errors (firstname vs first_name).
    Adds a backward-compatible key 'get_full_name' for templates using `user.get_full_name`.
    """
    first_name = getattr(user, "first_name", "") or ""
    last_name = getattr(user, "last_name", "") or ""
    full_name = f"{first_name} {last_name}".strip()
    return {
        "id": user.pk,
        "email": getattr(user, "email", "") or "",
        "first_name": first_name,
        "firstname": first_name,   # alias for templates using `firstname`
        "last_name": last_name,
        "lastname": last_name,     # alias for templates using `lastname`
        "full_name": full_name,
        "get_full_name": full_name,  # compatibility for templates using method-style access
    }

#----------------------------------------------------------------------------------------------------

# This function sends an email to the user for email verification after registration.
@shared_task
def send_email_verification_task(user_id):
    try:
        user = CustomUser.objects.get(pk=user_id)
    except CustomUser.DoesNotExist:
        logger.info(f"Task send_email_verification has failed. Invalid User ID was sent.")
        return 0
    
    uid = urlsafe_base64_encode(force_bytes(user.pk))
    # {changed} generate and store a per-user token
    token = user.generate_email_verification_token()
    verify_url = f"{settings.FRONTEND_URL}/email-verification/?uidb64={uid}&token={token}"

    context = {
        "user": _build_user_template_ctx(user),
        "action_url": verify_url,
        "frontend_url": settings.FRONTEND_URL,
        "cta_label": "Ověřit e‑mail",
    }

    send_email_with_context(
        recipients=user.email,
        subject="Ověření e‑mailu",
        template_name="email/email_verification.txt",
        html_template_name="email/email_verification.html",
        context=context,
    )



@shared_task
def send_email_test_task(email):
    context = {
        "action_url": settings.FRONTEND_URL,
        "frontend_url": settings.FRONTEND_URL,
        "cta_label": "Otevřít aplikaci",
    }
    send_email_with_context(
        recipients=email,
        subject="Testovací e‑mail",
        template_name="email/test.txt",
        html_template_name="email/test.html",
        context=context,
    )


@shared_task
def send_password_reset_email_task(user_id):
    try:
        user = CustomUser.objects.get(pk=user_id)
    except CustomUser.DoesNotExist:
        logger.info(f"Task send_password_reset_email has failed. Invalid User ID was sent.")
        return 0
    
    uid = urlsafe_base64_encode(force_bytes(user.pk))
    token = password_reset_token.make_token(user)
    reset_url = f"{settings.FRONTEND_URL}/reset-password/{uid}/{token}"

    context = {
        "user": _build_user_template_ctx(user),
        "action_url": reset_url,
        "frontend_url": settings.FRONTEND_URL,
        "cta_label": "Obnovit heslo",
    }

    send_email_with_context(
        recipients=user.email,
        subject="Obnova hesla",
        template_name="email/password_reset.txt",
        html_template_name="email/password_reset.html",
        context=context,
    )