from enum import Enum

import structlog
from constance import config
from django.conf import settings
from django.utils import timezone
from sendgrid import Mail, SendGridAPIClient

from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse

logger = structlog.get_logger(__name__)

DATETIME_FORMAT_SWISS_STR = "%d.%m.%Y %H:%M"


def format_swiss_datetime(dt: timezone.datetime) -> str:
    return dt.astimezone(timezone.get_current_timezone()).strftime(
        DATETIME_FORMAT_SWISS_STR
    )


class EmailTemplate(Enum):
    """Enum for the different Sendgrid email templates."""

    # VBV - Erinnerung Präsenzkurse
    ATTENDANCE_COURSE_REMINDER = {
        "de": "d-9af079f98f524d85ac6e4166de3480da",
        "it": "d-ab78ddca8a7a46b8afe50aaba3efee81",
        "fr": "d-f88d9912e5484e55a879571463e4a166",
    }

    ASSIGNMENT_REMINDER_CASEWORK_MEMBER = {
        "de": "d-8b84fd96213540a796c40d4344bc606f",
        "fr": "d-ae6cd87b6b574643b4fff209148c7620",
        "it": "d-1bf8b12a70324e1b91050d5fa01ed81f",
    }

    ASSIGNMENT_REMINDER_PREP_ASSIGNMENT_MEMBER = {
        "de": "d-cb866d8c538f4ffaab923022ef7209fa",
        "fr": "d-fdc84ae0e1b7417a8ede8db4e07ee7a8",
        "it": "d-39d16586341b4559b3a3df71db3d04fb",
    }

    ASSIGNMENT_REMINDER_EDONIQ_MEMBER = {
        "de": "d-4b26911d04834079a64ab1758ca470cc",
        "fr": "d-b9f27e3e13e44f20aa5d1a40c93da00d",
        "it": "d-1d3d854c5b3e4012ac3d33eeb3d6e7d1",
    }

    EVALUATION_REMINDER_CASEWORK_EXPERT = {
        "de": "d-6e3dd4acc7fc4ce7a2776f5147bd32fd",
        "fr": "d-0104add90a354d7fb1fc9fecfa132d06",
        "it": "d-630e9316960647768c0a657e175436aa",
    }

    # VBV - Geleitete Fallarbeit abgegeben
    CASEWORK_SUBMITTED = {"de": "d-599f0b35ddcd4fac99314cdf8f5446a2"}

    # VBV - Geleitete Fallarbeit bewertet
    CASEWORK_EVALUATED = {"de": "d-8c57fa13116b47be8eec95dfaf2aa030"}

    # VBV - Neues Feedback für Circle
    NEW_FEEDBACK = {"de": "d-40fb94d5149949e7b8e7ddfcf0fcfdde"}

    # Versicherungsvermittler (after buying a course)
    WELCOME_MAIL_VV = {
        "de": "d-308a72c779b74c8487cdec03c772ad13",
        "fr": "d-1a0958c7798c4dd18f730491e920eab5",
        "it": "d-0882ec9c92f64312b9f358481a943c9a",
    }


def send_email(
    recipient_email: str,
    template: EmailTemplate,
    template_data: dict,
    template_language: str = "de",
    fail_silently: bool = True,
) -> bool:
    log = logger.bind(
        recipient_email=recipient_email,
        template=template.name,
        template_data=template_data,
        template_language=template_language,
    )
    try:
        whitelist_emails = [
            email.strip()
            for email in config.EMAIL_RECIPIENT_WHITELIST.strip().split(",")
        ]
        if "*" in whitelist_emails or recipient_email in whitelist_emails:
            _send_sendgrid_email(
                recipient_email=recipient_email,
                template=template,
                template_data=template_data,
                template_language=template_language,
            )
            log.info("Email sent successfully")
            return True
        else:
            log.info("Email not sent because recipient is not whitelisted")
            return False
    except Exception as e:
        log.error(
            "Failed to send Email", exception=str(e), exc_info=True, stack_info=True
        )
        if not fail_silently:
            raise e
        return False


def _send_sendgrid_email(
    recipient_email: str,
    template: EmailTemplate,
    template_data: dict,
    template_language: str = "de",
) -> None:
    message = Mail(
        from_email="noreply@my.vbv-afa.ch",
        to_emails=recipient_email,
    )
    message.template_id = template.value.get(template_language, template.value["de"])
    message.dynamic_template_data = template_data
    SendGridAPIClient(settings.SENDGRID_API_KEY).send(message)


def create_template_data_from_course_session_attendance_course(
    attendance_course: CourseSessionAttendanceCourse,
):
    return {
        "attendance_course": attendance_course.learning_content.title,
        "location": attendance_course.location,
        "trainer": attendance_course.trainer,
        "start": format_swiss_datetime(attendance_course.due_date.start),
        "end": format_swiss_datetime(attendance_course.due_date.end),
    }
