"""
email_service.py — e-mails transactionnels Meeconic (SMTP TLS 587).

Deux envois :
  - send_order_confirmation()  → reçu HTML à la famille après commande
  - send_company_notification()→ alerte interne à l'équipe Meeconic

Variables .env (service transactionnel recommandé : Brevo ou Resend — PAS Gmail) :
    SMTP_HOST   (ex. smtp-relay.brevo.com / smtp.resend.com)
    SMTP_PORT   (587)
    SMTP_USER   (login SMTP)
    SMTP_PASS   (clé SMTP, pas le mot de passe du compte)
    SMTP_FROM   ("Meeconic <noreply@photos.meeconic.com>")  — défaut SMTP_USER
    COMPANY_NOTIFICATION_EMAIL  (destinataire des alertes internes)

Si SMTP n'est pas configuré, les fonctions renvoient False sans lever d'erreur.
"""
import html
import logging
import os
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

import aiosmtplib

log = logging.getLogger("meeconic.email")


def _cfg():
    host = os.getenv("SMTP_HOST", "smtp-relay.brevo.com")
    port = int(os.getenv("SMTP_PORT", "587"))
    user = os.getenv("SMTP_USER", "").strip()
    # les mots de passe d'application s'affichent parfois avec des espaces
    pw   = os.getenv("SMTP_PASSWORD", os.getenv("SMTP_PASS", "")).replace(" ", "")
    sender = os.getenv("SMTP_FROM", os.getenv("EMAIL_FROM", user)).strip()
    return host, port, user, pw, sender


def is_configured() -> bool:
    _, _, user, pw, _ = _cfg()
    return bool(user and pw)


def _items_rows(items: list[dict]) -> str:
    rows = ""
    for it in items:
        label = html.escape(str(it.get("format_label", "")))
        opt = html.escape(f"{it.get('job_label') or ''}") if it.get("is_magic") else ""
        qty = it.get("quantity", 1)
        price = it.get("unit_price", 0) * qty
        rows += (
            f"<tr><td style='padding:9px 12px;border-bottom:1px solid #F0EDE4;font-size:13px;color:#141B2E'>{label}</td>"
            f"<td style='padding:9px 12px;border-bottom:1px solid #F0EDE4;font-size:13px;color:#6E7585'>{opt}</td>"
            f"<td style='padding:9px 12px;border-bottom:1px solid #F0EDE4;font-size:13px;text-align:center;color:#6E7585'>{qty}</td>"
            f"<td style='padding:9px 12px;border-bottom:1px solid #F0EDE4;font-size:13px;text-align:right;font-family:monospace;color:#0A1F44'>{price:.0f} €</td></tr>"
        )
    return rows


def _confirmation_html(name: str, order_id: str, family_code: str, items: list[dict], total: float,
                       has_digital: bool = False, portal_url: str = "", attached: int = 0) -> str:
    name, family_code = html.escape(name or ""), html.escape(family_code)
    dl = ""
    if has_digital:
        link = html.escape(f"{portal_url.rstrip('/')}/?code={family_code}") if portal_url else ""
        cta = f' <a href="{link}" style="color:#0A1F44;font-weight:700">Ouvrir mon espace</a>' if link else ""
        # Attached originals are the real delivery; the portal link stays as the permanent fallback.
        lead = (f"Vos photos numériques HD sont jointes à cet e-mail ({attached}). "
                "Vous pouvez aussi les retrouver à tout moment" if attached else
                "Vos photos numériques HD sont disponibles au téléchargement")
        dl = ("<tr><td style='padding:18px 32px 0'><p style='margin:0;font-size:13px;color:#141B2E'>"
              + lead + " dans votre espace famille (rubrique « Mes commandes »)." + cta + "</p></td></tr>")
    return f"""<!DOCTYPE html>
<html lang="fr"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head>
<body style="margin:0;padding:0;background:#F7F4EE;font-family:Outfit,Arial,sans-serif">
  <table width="100%" cellpadding="0" cellspacing="0" style="background:#F7F4EE;padding:40px 0"><tr><td align="center">
    <table width="560" cellpadding="0" cellspacing="0" style="background:#fff;border-radius:16px;overflow:hidden;box-shadow:0 4px 24px rgba(10,31,68,.08);border:1px solid #E7E2D6">
      <tr><td style="background:linear-gradient(135deg,#071633,#0A1F44);padding:26px 32px">
        <div style="color:#fff;font-size:22px;font-weight:700;letter-spacing:3px">MEE<span style="color:#E8D48B">CO</span>NIC</div>
        <div style="color:rgba(255,255,255,.7);font-size:12px;margin-top:4px">L'instant d'école</div>
      </td></tr>
      <tr><td style="padding:28px 32px 0">
        <h1 style="margin:0;color:#0A1F44;font-size:24px;font-family:Georgia,serif">Commande confirmée !</h1>
        <p style="margin:12px 0 0;font-size:14px;color:#141B2E">Bonjour,</p>
        <p style="margin:8px 0 0;font-size:14px;color:#141B2E">Votre commande <strong>{order_id[:8].upper()}</strong> a bien été reçue.</p>
      </td></tr>
      <tr><td style="padding:18px 32px 0">
        <p style="margin:0;font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:.08em">Code famille</p>
        <p style="margin:4px 0 0;font-family:monospace;font-size:18px;font-weight:800;color:#0A1F44">{family_code}</p>
      </td></tr>
      <tr><td style="padding:18px 32px 0">
        <table width="100%" style="border-collapse:collapse;border:1px solid #F0EDE4;border-radius:10px;overflow:hidden">
          <thead><tr style="background:#F7F4EE">
            <th style="padding:9px 12px;text-align:left;font-size:10.5px;color:#6E7585;text-transform:uppercase">Format</th>
            <th style="padding:9px 12px;text-align:left;font-size:10.5px;color:#6E7585;text-transform:uppercase">Option</th>
            <th style="padding:9px 12px;text-align:center;font-size:10.5px;color:#6E7585;text-transform:uppercase">Qté</th>
            <th style="padding:9px 12px;text-align:right;font-size:10.5px;color:#6E7585;text-transform:uppercase">Prix</th>
          </tr></thead>
          <tbody>{_items_rows(items)}
            <tr><td colspan="3" style="padding:12px;border-top:2px solid #C9A227;font-weight:700;color:#0A1F44">Total payé</td>
                <td style="padding:12px;border-top:2px solid #C9A227;text-align:right;font-family:monospace;font-size:18px;font-weight:800;color:#0A1F44">{total:.0f} €</td></tr>
          </tbody>
        </table>
      </td></tr>
      {dl}<tr><td style="padding:24px 32px 0">
        <p style="margin:0;font-size:12px;color:#6E7585;line-height:1.6">Livraison des tirages en classe sous 5 à 10 jours ouvrés. Merci de votre confiance.</p>
      </td></tr>
      <tr><td style="padding:24px 0 0"><div style="height:5px;background:linear-gradient(90deg,#C9A227,#E8D48B)"></div></td></tr>
    </table>
  </td></tr></table>
</body></html>"""


async def _send(to: str, subject: str, html: str,
                attachments: list[tuple[str, bytes]] | None = None) -> bool:
    if not is_configured():
        log.warning("SMTP not configured — e-mail skipped (%s)", subject)
        return False
    host, port, user, pw, sender = _cfg()
    try:
        msg = MIMEMultipart("mixed" if attachments else "alternative")
        msg["Subject"] = subject
        msg["From"] = sender
        msg["To"] = to
        msg.attach(MIMEText(html, "html", "utf-8"))
        for fname, data in attachments or []:
            part = MIMEBase("application", "octet-stream")
            part.set_payload(data)
            encoders.encode_base64(part)
            part.add_header("Content-Disposition", "attachment", filename=fname)
            msg.attach(part)
        await aiosmtplib.send(msg, hostname=host, port=port, username=user, password=pw, start_tls=True)
        log.info("E-mail sent -> %s (%s)", to, subject)
        return True
    except Exception as e:
        log.error("E-mail sending failed -> %s: %s", to, e)
        return False


async def send_order_confirmation(to: str, name: str, order_id: str,
                                  family_code: str, items: list[dict], total: float,
                                  has_digital: bool = False, portal_url: str = "",
                                  attachments: list[tuple[str, bytes]] | None = None) -> bool:
    """Reçu de commande envoyé à la famille, avec les originaux HD en pièces jointes s'il y en a."""
    subject = f"Meeconic — Commande confirmée #{order_id[:8].upper()}"
    body = _confirmation_html(name, order_id, family_code, items, total, has_digital, portal_url,
                              attached=len(attachments or []))
    if await _send(to, subject, body, attachments):
        return True
    if not attachments:
        return False
    # The size limit is measured on the raw files but the message travels base64-encoded (+33 %), so a
    # server with a lower cap can refuse it. The confirmation must still arrive: resend it without the
    # files, the body then points to the portal download instead of claiming they are attached.
    log.warning("E-mail with %d attachment(s) refused for %s — resending without them", len(attachments), order_id)
    body = _confirmation_html(name, order_id, family_code, items, total, has_digital, portal_url, attached=0)
    return await _send(to, subject, body)


async def send_company_notification(order_id: str, family_code: str, customer_name: str,
                                    customer_email: str, items: list[dict], total: float,
                                    to: str = "") -> bool:
    """Alerte interne à l'équipe Meeconic (COMPANY_NOTIFICATION_EMAIL)."""
    to = (to or os.getenv("COMPANY_NOTIFICATION_EMAIL", "")).strip()
    if not to:
        return False
    rows = _items_rows(items)
    family_code_h, name_h, email_h = html.escape(family_code), html.escape(customer_name or ""), html.escape(customer_email or "")
    body = f"""<!DOCTYPE html><html><body style="font-family:Arial,sans-serif;background:#F7F4EE;padding:32px 0">
    <table width="560" cellpadding="0" cellspacing="0" style="margin:0 auto;background:#fff;border-radius:12px;overflow:hidden;border:1px solid #E7E2D6">
      <tr><td style="background:#0A1F44;padding:22px 32px">
        <div style="color:rgba(255,255,255,.7);font-size:11px;text-transform:uppercase;letter-spacing:.1em">Notification interne</div>
        <div style="color:#fff;font-size:19px;font-weight:700;margin-top:4px">🛒 Nouvelle commande</div></td></tr>
      <tr><td style="padding:22px 32px">
        <p style="margin:0 0 4px;font-size:11px;color:#6E7585;text-transform:uppercase">Code famille</p>
        <p style="margin:0 0 14px;font-size:20px;font-weight:800;color:#0A1F44;font-family:monospace">{family_code_h}</p>
        <p style="margin:4px 0;font-size:13px;color:#141B2E"><b>Classe :</b> {name_h} — {email_h}</p>
        <table width="100%" style="margin-top:14px;border-collapse:collapse;border:1px solid #F0EDE4;border-radius:8px;overflow:hidden"><tbody>{rows}</tbody></table>
        <p style="margin:14px 0 0;font-size:16px;font-weight:700;text-align:right;color:#0A1F44">Total : {total:.0f} €</p>
        <p style="margin:12px 0 0;font-size:11px;color:#9ca3af">ID commande : {order_id}</p>
      </td></tr>
      <tr><td><div style="height:4px;background:linear-gradient(90deg,#C9A227,#E8D48B)"></div></td></tr>
    </table></body></html>"""
    return await _send(to, f"🛒 Nouvelle commande — {family_code} — {total:.0f} €", body)


async def send_payment_failed(to: str, name: str, order_id: str, portal_url: str = "") -> bool:
    """Prévient la famille que son paiement a échoué (elle peut recommencer)."""
    link = f"<p><a href=\"{html.escape(portal_url)}\">Retourner sur le portail</a></p>" if portal_url else ""
    body = (f"<html><body style=\"font-family:Arial,sans-serif;color:#141B2E\">"
            f"<p>Bonjour,</p>"
            f"<p>Le paiement de votre commande <b>{order_id[:8].upper()}</b> n'a pas abouti. "
            f"Aucun montant n'a été débité. Vous pouvez recommencer votre commande depuis le portail.</p>{link}"
            f"<p>— L'équipe Meeconic</p></body></html>")
    return await _send(to, f"Meeconic — Paiement non abouti #{order_id[:8].upper()}", body)
