"""
Email service for QA Copilot.

Sends transactional emails via authenticated SMTP (e.g. Hostinger). Fails
silently when not configured — email must never break core functionality.
The public API (send_email, send_welcome, send_password_reset, …) is the
same as the previous SendGrid-based implementation so callers don't change.

Environment variables:
    QA_SMTP_HOST       — SMTP server hostname (e.g. smtp.hostinger.com)
    QA_SMTP_PORT       — SMTP port. 465 → implicit SSL (SMTPS). 587 → STARTTLS.
    QA_SMTP_USER       — SMTP username (typically the full sender address).
    QA_SMTP_PASSWORD   — SMTP password.
    QA_EMAIL_FROM      — Display-from address. Defaults to QA_SMTP_USER.
    QA_EMAIL_FROM_NAME — Optional display name, e.g. "QA Copilot".
"""
from __future__ import annotations

import html
import os
import smtplib
import ssl
from email.message import EmailMessage

SMTP_HOST     = os.environ.get("QA_SMTP_HOST", "")
SMTP_PORT     = int(os.environ.get("QA_SMTP_PORT", "587") or "587")
SMTP_USER     = os.environ.get("QA_SMTP_USER", "")
SMTP_PASSWORD = os.environ.get("QA_SMTP_PASSWORD", "")
EMAIL_FROM      = os.environ.get("QA_EMAIL_FROM", SMTP_USER or "contactus@qacopilot.fr")
EMAIL_FROM_NAME = os.environ.get("QA_EMAIL_FROM_NAME", "QA Copilot")
SMTP_TIMEOUT  = float(os.environ.get("QA_SMTP_TIMEOUT", "15") or "15")


def is_configured() -> bool:
    """Return True if outbound email is fully configured."""
    return bool(SMTP_HOST and SMTP_USER and SMTP_PASSWORD)


def _build_message(to: str, subject: str, html_body: str) -> EmailMessage:
    msg = EmailMessage()
    msg["Subject"] = subject
    msg["From"] = f"{EMAIL_FROM_NAME} <{EMAIL_FROM}>" if EMAIL_FROM_NAME else EMAIL_FROM
    msg["To"] = to
    # Plain-text fallback derived from the HTML so mail clients without HTML
    # rendering still get a readable body.
    plain = html.unescape(html_body)
    for tag in ("<br>", "<br/>", "<br />", "</p>", "</h1>", "</h2>", "</h3>", "</li>"):
        plain = plain.replace(tag, "\n")
    import re as _re
    plain = _re.sub(r"<[^>]+>", "", plain).strip()
    msg.set_content(plain or " ")
    msg.add_alternative(html_body, subtype="html")
    return msg


def send_email(to: str, subject: str, html_body: str) -> bool:
    """Send an email via SMTP. Returns True on success, False on failure."""
    if not is_configured():
        print(f"  ⚠  Email not sent (SMTP not configured): {subject}")
        return False
    try:
        msg = _build_message(to, subject, html_body)
        context = ssl.create_default_context()
        if SMTP_PORT == 465:
            with smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT, timeout=SMTP_TIMEOUT, context=context) as s:
                s.login(SMTP_USER, SMTP_PASSWORD)
                s.send_message(msg)
        else:
            with smtplib.SMTP(SMTP_HOST, SMTP_PORT, timeout=SMTP_TIMEOUT) as s:
                s.ehlo()
                s.starttls(context=context)
                s.ehlo()
                s.login(SMTP_USER, SMTP_PASSWORD)
                s.send_message(msg)
        return True
    except Exception as e:
        # Silent log: any failure here must not break the request that
        # triggered it (a failed welcome email still allows registration).
        print(f"  ⚠  Email send failed: {e}")
        return False


def send_welcome(email: str, username: str) -> bool:
    """Send welcome email after registration."""
    subject = "Welcome to QA Copilot"
    safe_username = html.escape(username)
    body = (
        f"<h2>Welcome, {safe_username}!</h2>"
        f"<p>Your QA Copilot account is ready. Start generating tests by logging in.</p>"
        f"<p>— The QA Copilot Team</p>"
    )
    return send_email(email, subject, body)


def send_password_reset(email: str, token: str, reset_url: str) -> bool:
    """Send password reset email with a time-limited link."""
    subject = "QA Copilot — Password Reset"
    link = f"{reset_url}?token={token}"
    body = (
        f"<h2>Password Reset</h2>"
        f"<p>Click the link below to reset your password. This link expires in 1 hour.</p>"
        f"<p><a href=\"{link}\">{link}</a></p>"
        f"<p>If you didn't request this, ignore this email.</p>"
    )
    return send_email(email, subject, body)


def send_email_verification(email: str, token: str, verify_url: str) -> bool:
    """Send an email-verification link to a freshly-registered account.

    Until the user clicks the link, login is blocked (see server.py).
    Token is opaque to this layer; storage and expiry are owned by the
    registration flow.
    """
    subject = "QA Copilot — Verify your email"
    link = f"{verify_url}?token={token}"
    body = (
        f"<h2>Verify your email</h2>"
        f"<p>Thanks for signing up for QA Copilot. To activate your account, "
        f"click the link below. The link expires in 24 hours.</p>"
        f"<p><a href=\"{link}\">{link}</a></p>"
        f"<p>If you didn't sign up for QA Copilot, you can safely ignore this email.</p>"
    )
    return send_email(email, subject, body)


def send_generation_complete(email: str, story_key: str, test_count: int) -> bool:
    """Notify user that test generation is complete."""
    safe_key = html.escape(story_key)
    subject = f"QA Copilot — Tests Generated for {safe_key}"
    body = (
        f"<h2>Generation Complete</h2>"
        f"<p>{test_count} test(s) generated for <strong>{safe_key}</strong>.</p>"
        f"<p>Log in to review and push them to Xray.</p>"
    )
    return send_email(email, subject, body)


def send_subscription_created(email: str, plan_name: str) -> bool:
    """Notify user that their subscription is active."""
    safe_plan = html.escape(plan_name)
    subject = f"QA Copilot — {safe_plan} Plan Activated"
    body = (
        f"<h2>Subscription Confirmed</h2>"
        f"<p>Your <strong>{safe_plan}</strong> plan is now active.</p>"
        f"<p>You now have full access to all generation features. Happy testing!</p>"
    )
    return send_email(email, subject, body)


def send_payment_failed(email: str) -> bool:
    """Alert user that a payment attempt failed."""
    subject = "QA Copilot — Payment Failed"
    body = (
        "<h2>Payment Issue</h2>"
        "<p>We were unable to process your latest payment. "
        "Please update your payment method to avoid service interruption.</p>"
        "<p>Log in to your account and visit Billing to update your card.</p>"
    )
    return send_email(email, subject, body)


def send_subscription_cancelled(email: str) -> bool:
    """Confirm subscription cancellation."""
    subject = "QA Copilot — Subscription Cancelled"
    body = (
        "<h2>Subscription Cancelled</h2>"
        "<p>Your subscription has been cancelled. You'll retain access until "
        "the end of your current billing period.</p>"
        "<p>We'd love to have you back — you can resubscribe anytime.</p>"
    )
    return send_email(email, subject, body)
