"""
Transactional email sender for the monthly reports.

Supports Postmark and Resend. If no API key is configured (or ATIME_EMAIL_DRY_RUN
is set), it does NOT send — it writes an .eml preview to output/ and prints what
it would have done. This makes local testing safe.
"""

import base64
import os

import config


def _attachment_part(att):
    """att = (filename, bytes, content_type)."""
    name, raw, ctype = att
    return name, base64.b64encode(raw).decode("ascii"), ctype


def _send_postmark(to, subject, html, attachments):
    import requests
    payload = {
        "From": config.EMAIL["from"],
        "To": ", ".join(to),
        "Subject": subject,
        "HtmlBody": html,
        "MessageStream": "outbound",
    }
    if config.EMAIL.get("reply_to"):
        payload["ReplyTo"] = config.EMAIL["reply_to"]
    if attachments:
        payload["Attachments"] = [
            {"Name": n, "Content": c, "ContentType": t}
            for (n, c, t) in (_attachment_part(a) for a in attachments)
        ]
    r = requests.post(
        "https://api.postmarkapp.com/email",
        headers={"X-Postmark-Server-Token": config.EMAIL["api_key"],
                 "Accept": "application/json", "Content-Type": "application/json"},
        json=payload, timeout=60)
    r.raise_for_status()
    return r.json()


def _send_resend(to, subject, html, attachments):
    import requests
    payload = {"from": config.EMAIL["from"], "to": list(to), "subject": subject, "html": html}
    if config.EMAIL.get("reply_to"):
        payload["reply_to"] = config.EMAIL["reply_to"]
    if attachments:
        payload["attachments"] = [
            {"filename": n, "content": c} for (n, c, _t) in (_attachment_part(a) for a in attachments)
        ]
    r = requests.post(
        "https://api.resend.com/emails",
        headers={"Authorization": f"Bearer {config.EMAIL['api_key']}",
                 "Content-Type": "application/json"},
        json=payload, timeout=60)
    r.raise_for_status()
    return r.json()


def _write_preview(to, subject, html, attachments):
    """Dry-run: write a .eml so the message (with attachments) can be opened/inspected."""
    from email.message import EmailMessage
    msg = EmailMessage()
    msg["From"] = config.EMAIL["from"]
    msg["To"] = ", ".join(to)
    msg["Subject"] = subject
    if config.EMAIL.get("reply_to"):
        msg["Reply-To"] = config.EMAIL["reply_to"]
    msg.set_content("This is the HTML report (open in an HTML-capable client).")
    msg.add_alternative(html, subtype="html")
    for name, raw, ctype in (attachments or []):
        maintype, _, subtype = ctype.partition("/")
        msg.add_attachment(raw, maintype=maintype or "application",
                           subtype=subtype or "octet-stream", filename=name)
    safe = subject.replace("/", "-").replace(" ", "_")[:60]
    path = os.path.join(config.OUTPUT_DIR, f"PREVIEW_{safe}.eml")
    with open(path, "wb") as f:
        f.write(bytes(msg))
    print(f"  [dry-run] would email {to} — subject '{subject}' "
          f"({len(attachments or [])} attachment(s)). Preview: {path}")
    return {"dry_run": True, "preview": path}


def send_email(to, subject, html, attachments=None):
    """Send one email. `to` is a list of addresses. attachments: list of (name, bytes, ctype)."""
    if not to:
        print(f"  [skip] no recipients for '{subject}'")
        return {"skipped": "no recipients"}
    if config.EMAIL["dry_run"] or not config.EMAIL.get("api_key"):
        return _write_preview(to, subject, html, attachments)
    provider = (config.EMAIL["provider"] or "postmark").lower()
    sender = _send_resend if provider == "resend" else _send_postmark
    result = sender(to, subject, html, attachments)
    print(f"  [sent:{provider}] {to} — '{subject}'")
    return result
