"""
Python 108 — Mailer
Console mode: emails are printed to terminal (no real sending).
To switch to real SMTP, set environment variables and MAIL_BACKEND='smtp'.

Environment variables for SMTP mode:
  MAIL_BACKEND   = smtp          (default: console)
  MAIL_HOST      = smtp.gmail.com
  MAIL_PORT      = 587
  MAIL_USERNAME  = you@gmail.com
  MAIL_PASSWORD  = your-app-password
  MAIL_FROM      = Python 108 <you@gmail.com>
"""
import os
import smtplib
import textwrap
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime


# ── Configuration ────────────────────────────────────────────────
MAIL_BACKEND  = os.environ.get("MAIL_BACKEND",  "console")
MAIL_HOST     = os.environ.get("MAIL_HOST",     "smtp.gmail.com")
MAIL_PORT     = int(os.environ.get("MAIL_PORT", "587"))
MAIL_USERNAME = os.environ.get("MAIL_USERNAME", "")
MAIL_PASSWORD = os.environ.get("MAIL_PASSWORD", "")
MAIL_FROM     = os.environ.get("MAIL_FROM",     "Python 108 <noreply@python108.local>")


# ── Core send function ───────────────────────────────────────────
def send_email(to: str, subject: str, body_text: str, body_html: str = None):
    """
    Send an email. In console mode, prints to terminal.
    In smtp mode, sends via SMTP.
    """
    if MAIL_BACKEND == "smtp":
        _send_smtp(to, subject, body_text, body_html)
    else:
        _send_console(to, subject, body_text)


def _send_console(to: str, subject: str, body: str):
    """Print email to terminal — useful for development."""
    border = "─" * 60
    print(f"\n{'═'*60}")
    print(f"  📧  EMAIL (console mode)")
    print(f"{'═'*60}")
    print(f"  To      : {to}")
    print(f"  Subject : {subject}")
    print(f"  Sent at : {datetime.now().strftime('%d %b %Y %H:%M:%S')}")
    print(f"{border}")
    for line in body.strip().split("\n"):
        print(f"  {line}")
    print(f"{'═'*60}\n")


def _send_smtp(to: str, subject: str, body_text: str, body_html: str = None):
    """Send via SMTP (Gmail / Outlook / custom)."""
    msg = MIMEMultipart("alternative")
    msg["Subject"] = subject
    msg["From"]    = MAIL_FROM
    msg["To"]      = to
    msg.attach(MIMEText(body_text, "plain"))
    if body_html:
        msg.attach(MIMEText(body_html, "html"))
    try:
        with smtplib.SMTP(MAIL_HOST, MAIL_PORT) as server:
            server.ehlo()
            server.starttls()
            server.login(MAIL_USERNAME, MAIL_PASSWORD)
            server.sendmail(MAIL_FROM, to, msg.as_string())
    except Exception as e:
        print(f"[MAIL ERROR] Failed to send to {to}: {e}")
        _send_console(to, subject, body_text)


# ── Email templates ──────────────────────────────────────────────
def send_welcome(username: str, email: str):
    subject = "Welcome to Python 108! 🐍"
    body = textwrap.dedent(f"""
        Hello {username},

        Welcome to Python 108 — your complete Python learning journey!

        You are now enrolled and ready to start. Here is what awaits you:

          • 108 programs — from Hello World to full OOP and data science
          • 108 exercises — one challenge per program
          • 12 module quizzes — test your knowledge
          • In-browser Python runner — code without any installation
          • Streak tracker — build a daily coding habit

        Get started at: http://localhost:5000

        Good luck and happy coding!

        — The Python 108 Team
    """).strip()
    send_email(email, subject, body)


def send_comment_notification(student_username: str, student_email: str,
                               teacher_username: str, program_n: int,
                               program_title: str, comment: str, rating: int):
    stars = "★" * rating + "☆" * (5 - rating)
    subject = f"New feedback on Program #{program_n} — Python 108"
    body = textwrap.dedent(f"""
        Hello {student_username},

        Your teacher {teacher_username} has left feedback on your work:

          Program : #{program_n} — {program_title}
          Rating  : {stars} ({rating}/5)

          "{comment}"

        View it at: http://localhost:5000/program/{program_n}

        Keep up the great work!

        — Python 108
    """).strip()
    send_email(student_email, subject, body)


def send_password_reset(username: str, email: str, token: str, base_url: str = "http://localhost:5000"):
    reset_url = f"{base_url}/reset-password/{token}"
    subject   = "Python 108 — Password Reset Request"
    body = textwrap.dedent(f"""
        Hello {username},

        We received a request to reset your Python 108 password.

        Click the link below to set a new password:

          {reset_url}

        This link expires in 1 hour.

        If you did not request a password reset, you can safely ignore this email.
        Your password will not be changed.

        — Python 108
    """).strip()
    send_email(email, subject, body)


def send_announcement(student_username: str, student_email: str,
                       class_name: str, title: str, body_text: str,
                       teacher_username: str):
    subject = f"[{class_name}] {title}"
    body = textwrap.dedent(f"""
        Hello {student_username},

        Your teacher {teacher_username} has posted an announcement for {class_name}:

        {title}
        {"─" * len(title)}
        {body_text}

        View it at: http://localhost:5000/dashboard

        — Python 108
    """).strip()
    send_email(student_email, subject, body)


def send_assignment_notification(student_username: str, student_email: str,
                                  program_n: int, program_title: str,
                                  due_date: str, note: str, class_name: str):
    subject = f"New Assignment: #{program_n} {program_title} — Python 108"
    note_line = f"\n          Note    : {note}" if note else ""
    body = textwrap.dedent(f"""
        Hello {student_username},

        Your teacher has assigned a new program for {class_name}:

          Program  : #{program_n} — {program_title}
          Due date : {due_date}{note_line}

        Start it at: http://localhost:5000/program/{program_n}

        — Python 108
    """).strip()
    send_email(student_email, subject, body)
