from datetime import UTC, datetime

import structlog
from apscheduler.schedulers.background import BackgroundScheduler
from django.core.mail import send_mail
from django.template.loader import render_to_string

from config import settings
from config.settings import FRONTEND_URLS
from letters.models import Letter

logger = structlog.get_logger(__name__)


def get_vault_letters_to_notify():
    """
    Identifies the vault letters that have been recently unlocked and not notified
    """
    return Letter.objects.filter(unlock_at__lt=datetime.now(UTC), notified_at=None)


def notify_unlocked_letter(letter):
    """
    Notifies the author of the letter via email and if successful, updates the notified_at field for the letter.
    """
    author = letter.user.get_username()
    try:
        letter_link = f"{FRONTEND_URLS[0]}/read/{letter.public_id}"
        subject = "A letter. Written for this exact moment."
        context = {
            "pen_name": letter.user.first_name,
            "cta": {"title": "View what you wrote", "link": letter_link},
            "footnote": True,
        }
        plaint_content = render_to_string("email/vault_unlock.txt", context=context)
        html_content = render_to_string("email/vault_unlock.html", context=context)
        send_mail(
            subject=subject,
            message=plaint_content,
            from_email=settings.FROM_EMAIL,
            recipient_list=[author],
            fail_silently=False,
            html_message=html_content,
        )
        letter.notified_at = datetime.now(UTC)
        letter.save()
        logger.info(f"Successfully notified {author} of unlocked letter")
    except Exception:
        logger.exception(f"Failed to notify {author} of unlocked letter")


def vault_unlock_notification_polling_scheduler():
    """
    Orchestrates the vault polling logic.
    """
    letters_to_notify = get_vault_letters_to_notify()
    for letter in letters_to_notify:
        notify_unlocked_letter(letter)


def start_scheduler():
    """
    Starts the background scheduler for polling and notifying vault letters.
    """
    logger.info("Starting vault polling scheduler...")
    scheduler = BackgroundScheduler()
    scheduler.add_job(
        vault_unlock_notification_polling_scheduler,
        trigger="interval",
        minutes=1,
        id="letter_polling",
        replace_existing=True,
    )
    scheduler.start()
