"""
Tests for all transactional email worker handlers.

Each handler is tested by mocking send_email and calling the handler
directly with a payload. Assertions cover: recipient, subject keywords,
HTML content (design elements, i18n keys resolved), and from_addr.

The TestResendLive class at the bottom sends real emails via Resend's
@resend.dev test addresses. Skipped unless RESEND_API_KEY is set.
"""

import asyncio
import os
from datetime import UTC, datetime
from unittest.mock import AsyncMock, patch

import pytest
from padelnomics.worker import (
    handle_send_lead_forward_email,
    handle_send_lead_matched_notification,
    handle_send_magic_link,
    handle_send_quote_verification,
    handle_send_supplier_enquiry_email,
    handle_send_waitlist_confirmation,
    handle_send_welcome,
)

from padelnomics import core

# ── Helpers ──────────────────────────────────────────────────────


def _call_kwargs(mock_send: AsyncMock) -> dict:
    """Extract kwargs from first call to mock send_email."""
    mock_send.assert_called_once()
    return mock_send.call_args.kwargs


def _assert_common_design(html: str, lang: str = "en"):
    """Verify shared email wrapper design elements are present."""
    assert "padelnomics" in html  # wordmark
    assert "Bricolage Grotesque" in html  # brand font
    assert "#1D4ED8" in html  # blue accent / button
    assert "padelnomics.io" in html  # footer link
    assert f'lang="{lang}"' in html  # html lang attribute


# ── Magic Link ───────────────────────────────────────────────────


class TestMagicLink:
    @pytest.mark.asyncio
    async def test_sends_to_correct_recipient(self, mock_send_email):
        await handle_send_magic_link({"email": "user@example.com", "token": "abc123"})
        kw = _call_kwargs(mock_send_email)
        assert kw["to"] == "user@example.com"

    @pytest.mark.asyncio
    async def test_subject_contains_app_name(self, mock_send_email):
        await handle_send_magic_link({"email": "user@example.com", "token": "abc123"})
        kw = _call_kwargs(mock_send_email)
        assert core.config.APP_NAME.lower() in kw["subject"].lower()

    @pytest.mark.asyncio
    async def test_html_contains_verify_link(self, mock_send_email):
        await handle_send_magic_link({"email": "user@example.com", "token": "abc123"})
        kw = _call_kwargs(mock_send_email)
        assert "/auth/verify?token=abc123" in kw["html"]

    @pytest.mark.asyncio
    async def test_html_contains_fallback_link_text(self, mock_send_email):
        await handle_send_magic_link({"email": "user@example.com", "token": "tok"})
        html = _call_kwargs(mock_send_email)["html"]
        assert "word-break:break-all" in html  # fallback URL block

    @pytest.mark.asyncio
    async def test_uses_transactional_from_addr(self, mock_send_email):
        await handle_send_magic_link({"email": "user@example.com", "token": "tok"})
        assert _call_kwargs(mock_send_email)["from_addr"] == core.EMAIL_ADDRESSES["transactional"]

    @pytest.mark.asyncio
    async def test_preheader_mentions_expiry(self, mock_send_email):
        await handle_send_magic_link({"email": "user@example.com", "token": "tok"})
        html = _call_kwargs(mock_send_email)["html"]
        # preheader is hidden span; should mention minutes
        assert "display:none" in html  # preheader present

    @pytest.mark.asyncio
    async def test_design_elements_present(self, mock_send_email):
        await handle_send_magic_link({"email": "user@example.com", "token": "tok"})
        _assert_common_design(_call_kwargs(mock_send_email)["html"])

    @pytest.mark.asyncio
    async def test_respects_lang_parameter(self, mock_send_email):
        await handle_send_magic_link({"email": "user@example.com", "token": "tok", "lang": "de"})
        html = _call_kwargs(mock_send_email)["html"]
        _assert_common_design(html, lang="de")


# ── Welcome ──────────────────────────────────────────────────────


class TestWelcome:
    @pytest.mark.asyncio
    async def test_sends_to_correct_recipient(self, mock_send_email):
        await handle_send_welcome({"email": "new@example.com"})
        assert _call_kwargs(mock_send_email)["to"] == "new@example.com"

    @pytest.mark.asyncio
    async def test_subject_not_empty(self, mock_send_email):
        await handle_send_welcome({"email": "new@example.com"})
        assert len(_call_kwargs(mock_send_email)["subject"]) > 5

    @pytest.mark.asyncio
    async def test_html_contains_quickstart_links(self, mock_send_email):
        await handle_send_welcome({"email": "new@example.com"})
        html = _call_kwargs(mock_send_email)["html"]
        assert "/planner" in html
        assert "/markets" in html
        assert "/leads/quote" in html

    @pytest.mark.asyncio
    async def test_uses_first_name_when_provided(self, mock_send_email):
        await handle_send_welcome({"email": "new@example.com", "name": "Alice Smith"})
        html = _call_kwargs(mock_send_email)["html"]
        assert "Alice" in html

    @pytest.mark.asyncio
    async def test_fallback_greeting_when_no_name(self, mock_send_email):
        await handle_send_welcome({"email": "new@example.com"})
        html = _call_kwargs(mock_send_email)["html"]
        # Should use "there" as fallback first_name
        assert "there" in html.lower()

    @pytest.mark.asyncio
    async def test_uses_transactional_from_addr(self, mock_send_email):
        await handle_send_welcome({"email": "new@example.com"})
        assert _call_kwargs(mock_send_email)["from_addr"] == core.EMAIL_ADDRESSES["transactional"]

    @pytest.mark.asyncio
    async def test_design_elements_present(self, mock_send_email):
        await handle_send_welcome({"email": "new@example.com"})
        _assert_common_design(_call_kwargs(mock_send_email)["html"])

    @pytest.mark.asyncio
    async def test_german_welcome(self, mock_send_email):
        await handle_send_welcome({"email": "new@example.com", "lang": "de"})
        html = _call_kwargs(mock_send_email)["html"]
        _assert_common_design(html, lang="de")


# ── Quote Verification ───────────────────────────────────────────


class TestQuoteVerification:
    _BASE_PAYLOAD = {
        "email": "lead@example.com",
        "token": "verify_tok",
        "lead_token": "lead_tok",
        "contact_name": "Bob Builder",
        "court_count": 6,
        "facility_type": "Indoor",
        "country": "Germany",
    }

    @pytest.mark.asyncio
    async def test_sends_to_contact_email(self, mock_send_email):
        await handle_send_quote_verification(self._BASE_PAYLOAD)
        assert _call_kwargs(mock_send_email)["to"] == "lead@example.com"

    @pytest.mark.asyncio
    async def test_html_contains_verify_link(self, mock_send_email):
        await handle_send_quote_verification(self._BASE_PAYLOAD)
        html = _call_kwargs(mock_send_email)["html"]
        assert "token=verify_tok" in html
        assert "lead=lead_tok" in html

    @pytest.mark.asyncio
    async def test_html_contains_project_recap(self, mock_send_email):
        await handle_send_quote_verification(self._BASE_PAYLOAD)
        html = _call_kwargs(mock_send_email)["html"]
        assert "6 courts" in html
        assert "Indoor" in html
        assert "Germany" in html

    @pytest.mark.asyncio
    async def test_uses_first_name_from_contact(self, mock_send_email):
        await handle_send_quote_verification(self._BASE_PAYLOAD)
        html = _call_kwargs(mock_send_email)["html"]
        assert "Bob" in html

    @pytest.mark.asyncio
    async def test_handles_minimal_payload(self, mock_send_email):
        """No court_count/facility_type/country — should still send."""
        await handle_send_quote_verification({
            "email": "lead@example.com",
            "token": "tok",
            "lead_token": "ltok",
        })
        mock_send_email.assert_called_once()

    @pytest.mark.asyncio
    async def test_uses_transactional_from_addr(self, mock_send_email):
        await handle_send_quote_verification(self._BASE_PAYLOAD)
        assert _call_kwargs(mock_send_email)["from_addr"] == core.EMAIL_ADDRESSES["transactional"]

    @pytest.mark.asyncio
    async def test_design_elements_present(self, mock_send_email):
        await handle_send_quote_verification(self._BASE_PAYLOAD)
        _assert_common_design(_call_kwargs(mock_send_email)["html"])


# ── Lead Forward (the money email) ──────────────────────────────


class TestLeadForward:
    @pytest.mark.asyncio
    async def test_sends_to_supplier_email(self, db, mock_send_email):
        lead_id, supplier_id = await _seed_lead_and_supplier(db)
        await handle_send_lead_forward_email({"lead_id": lead_id, "supplier_id": supplier_id})
        assert _call_kwargs(mock_send_email)["to"] == "supplier@test.com"

    @pytest.mark.asyncio
    async def test_subject_contains_heat_and_country(self, db, mock_send_email):
        lead_id, supplier_id = await _seed_lead_and_supplier(db)
        await handle_send_lead_forward_email({"lead_id": lead_id, "supplier_id": supplier_id})
        subject = _call_kwargs(mock_send_email)["subject"]
        assert "[HOT]" in subject
        assert "Germany" in subject
        assert "4 courts" in subject

    @pytest.mark.asyncio
    async def test_html_contains_heat_badge(self, db, mock_send_email):
        lead_id, supplier_id = await _seed_lead_and_supplier(db)
        await handle_send_lead_forward_email({"lead_id": lead_id, "supplier_id": supplier_id})
        html = _call_kwargs(mock_send_email)["html"]
        assert "#DC2626" in html  # HOT badge color
        assert "HOT" in html

    @pytest.mark.asyncio
    async def test_html_contains_project_brief(self, db, mock_send_email):
        lead_id, supplier_id = await _seed_lead_and_supplier(db)
        await handle_send_lead_forward_email({"lead_id": lead_id, "supplier_id": supplier_id})
        html = _call_kwargs(mock_send_email)["html"]
        assert "Indoor" in html
        assert "Germany" in html

    @pytest.mark.asyncio
    async def test_html_contains_contact_info(self, db, mock_send_email):
        lead_id, supplier_id = await _seed_lead_and_supplier(db)
        await handle_send_lead_forward_email({"lead_id": lead_id, "supplier_id": supplier_id})
        html = _call_kwargs(mock_send_email)["html"]
        assert "lead@buyer.com" in html
        assert "mailto:lead@buyer.com" in html
        assert "John Doe" in html

    @pytest.mark.asyncio
    async def test_html_contains_urgency_callout(self, db, mock_send_email):
        lead_id, supplier_id = await _seed_lead_and_supplier(db)
        await handle_send_lead_forward_email({"lead_id": lead_id, "supplier_id": supplier_id})
        html = _call_kwargs(mock_send_email)["html"]
        # Urgency callout has yellow background
        assert "#FEF3C7" in html

    @pytest.mark.asyncio
    async def test_html_contains_direct_reply_cta(self, db, mock_send_email):
        lead_id, supplier_id = await _seed_lead_and_supplier(db)
        await handle_send_lead_forward_email({"lead_id": lead_id, "supplier_id": supplier_id})
        html = _call_kwargs(mock_send_email)["html"]
        # Direct reply link text should mention the contact email
        assert "lead@buyer.com" in html

    @pytest.mark.asyncio
    async def test_uses_leads_from_addr(self, db, mock_send_email):
        lead_id, supplier_id = await _seed_lead_and_supplier(db)
        await handle_send_lead_forward_email({"lead_id": lead_id, "supplier_id": supplier_id})
        assert _call_kwargs(mock_send_email)["from_addr"] == core.EMAIL_ADDRESSES["leads"]

    @pytest.mark.asyncio
    async def test_updates_email_sent_at(self, db, mock_send_email):
        lead_id, supplier_id = await _seed_lead_and_supplier(db, create_forward=True)
        await handle_send_lead_forward_email({"lead_id": lead_id, "supplier_id": supplier_id})

        async with db.execute(
            "SELECT email_sent_at FROM lead_forwards WHERE lead_id = ? AND supplier_id = ?",
            (lead_id, supplier_id),
        ) as cursor:
            row = await cursor.fetchone()
            assert row is not None
            assert row["email_sent_at"] is not None

    @pytest.mark.asyncio
    async def test_skips_when_no_supplier_email(self, db, mock_send_email):
        """No email on supplier record — handler exits without sending."""
        lead_id, supplier_id = await _seed_lead_and_supplier(db, supplier_email="")
        await handle_send_lead_forward_email({"lead_id": lead_id, "supplier_id": supplier_id})
        mock_send_email.assert_not_called()

    @pytest.mark.asyncio
    async def test_skips_when_lead_not_found(self, db, mock_send_email):
        """Non-existent lead_id — handler exits without sending."""
        _, supplier_id = await _seed_lead_and_supplier(db)
        await handle_send_lead_forward_email({"lead_id": 99999, "supplier_id": supplier_id})
        mock_send_email.assert_not_called()

    @pytest.mark.asyncio
    async def test_design_elements_present(self, db, mock_send_email):
        lead_id, supplier_id = await _seed_lead_and_supplier(db)
        await handle_send_lead_forward_email({"lead_id": lead_id, "supplier_id": supplier_id})
        _assert_common_design(_call_kwargs(mock_send_email)["html"])


# ── Lead Matched Notification ────────────────────────────────────


class TestLeadMatched:
    @pytest.mark.asyncio
    async def test_sends_to_lead_contact_email(self, db, mock_send_email):
        lead_id = await _seed_lead(db)
        await handle_send_lead_matched_notification({"lead_id": lead_id})
        assert _call_kwargs(mock_send_email)["to"] == "lead@buyer.com"

    @pytest.mark.asyncio
    async def test_subject_contains_first_name(self, db, mock_send_email):
        lead_id = await _seed_lead(db)
        await handle_send_lead_matched_notification({"lead_id": lead_id})
        assert "John" in _call_kwargs(mock_send_email)["subject"]

    @pytest.mark.asyncio
    async def test_html_contains_what_happens_next(self, db, mock_send_email):
        lead_id = await _seed_lead(db)
        await handle_send_lead_matched_notification({"lead_id": lead_id})
        html = _call_kwargs(mock_send_email)["html"]
        # "What happens next" section and tip callout (blue bg)
        assert "#F0F9FF" in html  # tip callout background

    @pytest.mark.asyncio
    async def test_html_contains_project_context(self, db, mock_send_email):
        lead_id = await _seed_lead(db)
        await handle_send_lead_matched_notification({"lead_id": lead_id})
        html = _call_kwargs(mock_send_email)["html"]
        assert "Indoor" in html
        assert "Germany" in html

    @pytest.mark.asyncio
    async def test_uses_leads_from_addr(self, db, mock_send_email):
        lead_id = await _seed_lead(db)
        await handle_send_lead_matched_notification({"lead_id": lead_id})
        assert _call_kwargs(mock_send_email)["from_addr"] == core.EMAIL_ADDRESSES["leads"]

    @pytest.mark.asyncio
    async def test_skips_when_lead_not_found(self, db, mock_send_email):
        await handle_send_lead_matched_notification({"lead_id": 99999})
        mock_send_email.assert_not_called()

    @pytest.mark.asyncio
    async def test_skips_when_no_contact_email(self, db, mock_send_email):
        lead_id = await _seed_lead(db, contact_email="")
        await handle_send_lead_matched_notification({"lead_id": lead_id})
        mock_send_email.assert_not_called()

    @pytest.mark.asyncio
    async def test_design_elements_present(self, db, mock_send_email):
        lead_id = await _seed_lead(db)
        await handle_send_lead_matched_notification({"lead_id": lead_id})
        _assert_common_design(_call_kwargs(mock_send_email)["html"])


# ── Supplier Enquiry ─────────────────────────────────────────────


class TestSupplierEnquiry:
    _BASE_PAYLOAD = {
        "supplier_email": "supplier@corp.com",
        "supplier_name": "PadelBuild GmbH",
        "contact_name": "Alice Smith",
        "contact_email": "alice@buyer.com",
        "message": "I need 4 courts, can you quote?",
    }

    @pytest.mark.asyncio
    async def test_sends_to_supplier_email(self, mock_send_email):
        await handle_send_supplier_enquiry_email(self._BASE_PAYLOAD)
        assert _call_kwargs(mock_send_email)["to"] == "supplier@corp.com"

    @pytest.mark.asyncio
    async def test_subject_contains_contact_name(self, mock_send_email):
        await handle_send_supplier_enquiry_email(self._BASE_PAYLOAD)
        assert "Alice Smith" in _call_kwargs(mock_send_email)["subject"]

    @pytest.mark.asyncio
    async def test_html_contains_message(self, mock_send_email):
        await handle_send_supplier_enquiry_email(self._BASE_PAYLOAD)
        html = _call_kwargs(mock_send_email)["html"]
        assert "4 courts" in html
        assert "alice@buyer.com" in html

    @pytest.mark.asyncio
    async def test_html_contains_respond_fast_nudge(self, mock_send_email):
        await handle_send_supplier_enquiry_email(self._BASE_PAYLOAD)
        html = _call_kwargs(mock_send_email)["html"]
        # The respond-fast nudge line should be present
        assert "24" in html  # "24 hours" reference

    @pytest.mark.asyncio
    async def test_skips_when_no_supplier_email(self, mock_send_email):
        await handle_send_supplier_enquiry_email({**self._BASE_PAYLOAD, "supplier_email": ""})
        mock_send_email.assert_not_called()

    @pytest.mark.asyncio
    async def test_uses_transactional_from_addr(self, mock_send_email):
        await handle_send_supplier_enquiry_email(self._BASE_PAYLOAD)
        assert _call_kwargs(mock_send_email)["from_addr"] == core.EMAIL_ADDRESSES["transactional"]

    @pytest.mark.asyncio
    async def test_design_elements_present(self, mock_send_email):
        await handle_send_supplier_enquiry_email(self._BASE_PAYLOAD)
        _assert_common_design(_call_kwargs(mock_send_email)["html"])


# ── Waitlist (supplement existing test_waitlist.py) ──────────────


class TestWaitlistEmails:
    """Verify design & content for waitlist confirmation emails."""

    @pytest.mark.asyncio
    async def test_general_waitlist_has_preheader(self, mock_send_email):
        await handle_send_waitlist_confirmation({"email": "u@example.com", "intent": "signup"})
        html = _call_kwargs(mock_send_email)["html"]
        assert "display:none" in html  # preheader span

    @pytest.mark.asyncio
    async def test_supplier_waitlist_mentions_plan(self, mock_send_email):
        await handle_send_waitlist_confirmation({"email": "s@example.com", "intent": "supplier_growth"})
        kw = _call_kwargs(mock_send_email)
        assert "growth" in kw["subject"].lower()
        assert "supplier" in kw["html"].lower()

    @pytest.mark.asyncio
    async def test_general_waitlist_design_elements(self, mock_send_email):
        await handle_send_waitlist_confirmation({"email": "u@example.com", "intent": "signup"})
        _assert_common_design(_call_kwargs(mock_send_email)["html"])

    @pytest.mark.asyncio
    async def test_supplier_waitlist_perks_listed(self, mock_send_email):
        await handle_send_waitlist_confirmation({"email": "s@example.com", "intent": "supplier_pro"})
        html = _call_kwargs(mock_send_email)["html"]
        # Should have <li> perks
        assert html.count("<li>") >= 3


# ── DB seed helpers ──────────────────────────────────────────────


async def _seed_lead(
    db,
    contact_email: str = "lead@buyer.com",
    contact_name: str = "John Doe",
) -> int:
    """Insert a lead_request row, return its id."""
    now = datetime.now(UTC).isoformat()
    async with db.execute(
        """INSERT INTO lead_requests (
            lead_type, contact_name, contact_email, contact_phone,
            contact_company, stakeholder_type, facility_type, court_count,
            country, location, build_context, glass_type, lighting_type,
            timeline, budget_estimate, location_status, financing_status,
            services_needed, additional_info, heat_score,
            status, created_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
        (
            "quote", contact_name, contact_email, "+49123456",
            "Padel Corp", "investor", "Indoor", 4,
            "Germany", "Berlin", "new_build", "tempered", "LED",
            "6-12 months", 200000, "secured", "seeking",
            "construction, lighting", "Need turnkey solution", "hot",
            "verified", now,
        ),
    ) as cursor:
        lead_id = cursor.lastrowid
    await db.commit()
    return lead_id


async def _seed_supplier(
    db,
    contact_email: str = "supplier@test.com",
) -> int:
    """Insert a supplier row, return its id."""
    now = datetime.now(UTC).isoformat()
    async with db.execute(
        """INSERT INTO suppliers (
            name, slug, country_code, region, category,
            contact_email, tier, claimed_by, created_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
        (
            "Test Supplier", "test-supplier", "DE", "Europe", "construction",
            contact_email, "growth", None, now,
        ),
    ) as cursor:
        supplier_id = cursor.lastrowid
    await db.commit()
    return supplier_id


async def _seed_lead_and_supplier(
    db,
    supplier_email: str = "supplier@test.com",
    create_forward: bool = False,
) -> tuple[int, int]:
    """Insert a lead + supplier pair, optionally with a lead_forwards row."""
    lead_id = await _seed_lead(db)
    supplier_id = await _seed_supplier(db, contact_email=supplier_email)

    if create_forward:
        now = datetime.now(UTC).isoformat()
        await db.execute(
            """INSERT INTO lead_forwards (lead_id, supplier_id, credit_cost, created_at)
               VALUES (?, ?, ?, ?)""",
            (lead_id, supplier_id, 1, now),
        )
        await db.commit()

    return lead_id, supplier_id


# ── Live Resend integration tests ────────────────────────────────
#
# These send real emails to Resend's @resend.dev test addresses,
# then retrieve the sent email via resend.Emails.get() to verify the
# rendered HTML contains expected design elements and content.
#
# Skipped unless RESEND_API_KEY is set in the environment.
# Run with:  RESEND_API_KEY=re_xxx uv run pytest web/tests/test_emails.py -k resend_live -v

_has_resend_key = bool(os.environ.get("RESEND_API_KEY"))
_skip_no_key = pytest.mark.skipif(not _has_resend_key, reason="RESEND_API_KEY not set")


def _send_and_capture():
    """Patch resend.Emails.send to capture the returned email ID.

    Returns (wrapper, captured) where captured is a dict that will
    contain {"id": ...} after send is called.  The real send still
    executes — this just grabs the return value that core.send_email
    discards.
    """
    import resend as _resend

    _original_send = _resend.Emails.send
    captured = {}

    def _wrapper(params):
        result = _original_send(params)
        captured["id"] = result.id if hasattr(result, "id") else result.get("id")
        return result

    return _wrapper, captured


def _retrieve_html(captured: dict) -> str | None:
    """Retrieve the sent email from Resend and return its HTML.

    Returns None if:
    - The send failed (rate limit, network error) — captured has no id
    - The API key lacks read permission (sending_access only)
    """
    import resend as _resend

    email_id = captured.get("id")
    if not email_id:
        return None  # send failed (e.g. rate limit) — can't retrieve
    try:
        email = _resend.Emails.get(email_id)
    except Exception:
        # sending_access key — can't retrieve, that's OK
        return None
    return email.html if hasattr(email, "html") else email.get("html", "")


@_skip_no_key
class TestResendLive:
    """Send real emails via Resend to @resend.dev test addresses.

    Uses ``delivered@resend.dev`` which simulates successful delivery.
    After sending, retrieves the email via resend.Emails.get() and
    asserts on the rendered HTML (design elements, content, structure).

    Each test calls the handler WITHOUT mocking send_email, so the full
    path is exercised: handler → _email_wrap → send_email → Resend API.
    """

    @pytest.fixture(autouse=True)
    async def _set_resend_key(self):
        """Ensure config picks up the real API key from env.

        Adds a 0.6s pause between tests to respect Resend's 2 req/sec
        rate limit.
        """
        import resend as _resend

        original = core.config.RESEND_API_KEY
        core.config.RESEND_API_KEY = os.environ["RESEND_API_KEY"]
        _resend.api_key = os.environ["RESEND_API_KEY"]
        yield
        core.config.RESEND_API_KEY = original
        await asyncio.sleep(0.6)

    def _check_html(self, captured: dict, assertions: list[tuple[str, str]]):
        """Retrieve sent email and run assertions on HTML.

        If the API key lacks read permission (sending_access only),
        the retrieve is skipped — the test still passes because the
        send itself succeeded (no exception from handler).

        assertions: list of (needle, description) tuples.
        """
        html = _retrieve_html(captured)
        if html is None:
            return  # sending_access key — can't retrieve, send was enough
        for needle, desc in assertions:
            assert needle in html, f"Expected {desc!r} ({needle!r}) in rendered HTML"

    @pytest.mark.asyncio
    async def test_magic_link_delivered(self):
        wrapper, captured = _send_and_capture()
        with patch("resend.Emails.send", side_effect=wrapper):
            await handle_send_magic_link({
                "email": "delivered@resend.dev",
                "token": "test_token_magic",
                "lang": "en",
            })
        self._check_html(captured, [
            ("padelnomics", "wordmark"),
            ("Bricolage Grotesque", "brand font"),
            ("/auth/verify?token=test_token_magic", "verify link"),
            ("padelnomics.io", "footer link"),
        ])

    @pytest.mark.asyncio
    async def test_welcome_delivered(self):
        wrapper, captured = _send_and_capture()
        with patch("resend.Emails.send", side_effect=wrapper):
            await handle_send_welcome({
                "email": "delivered@resend.dev",
                "name": "Test User",
                "lang": "en",
            })
        self._check_html(captured, [
            ("Test", "first name"),
            ("/planner", "planner link"),
            ("/markets", "markets link"),
            ("/leads/quote", "quotes link"),
        ])

    @pytest.mark.asyncio
    async def test_quote_verification_delivered(self):
        wrapper, captured = _send_and_capture()
        with patch("resend.Emails.send", side_effect=wrapper):
            await handle_send_quote_verification({
                "email": "delivered@resend.dev",
                "token": "test_verify_tok",
                "lead_token": "test_lead_tok",
                "contact_name": "Test Buyer",
                "court_count": 4,
                "facility_type": "Indoor",
                "country": "Germany",
                "lang": "en",
            })
        self._check_html(captured, [
            ("4 courts", "court count"),
            ("Indoor", "facility type"),
            ("Germany", "country"),
            ("token=test_verify_tok", "verify token"),
        ])

    @pytest.mark.asyncio
    async def test_waitlist_general_delivered(self):
        wrapper, captured = _send_and_capture()
        with patch("resend.Emails.send", side_effect=wrapper):
            await handle_send_waitlist_confirmation({
                "email": "delivered@resend.dev",
                "intent": "signup",
                "lang": "en",
            })
        self._check_html(captured, [
            ("padelnomics", "wordmark"),
            ("<li>", "perk bullets"),
        ])

    @pytest.mark.asyncio
    async def test_waitlist_supplier_delivered(self):
        wrapper, captured = _send_and_capture()
        with patch("resend.Emails.send", side_effect=wrapper):
            await handle_send_waitlist_confirmation({
                "email": "delivered@resend.dev",
                "intent": "supplier_growth",
                "lang": "en",
            })
        self._check_html(captured, [
            ("Growth", "plan name"),
        ])

    @pytest.mark.asyncio
    async def test_lead_forward_delivered(self, db):
        lead_id, supplier_id = await _seed_lead_and_supplier(
            db, supplier_email="delivered@resend.dev",
        )
        wrapper, captured = _send_and_capture()
        with patch("resend.Emails.send", side_effect=wrapper):
            await handle_send_lead_forward_email({
                "lead_id": lead_id,
                "supplier_id": supplier_id,
                "lang": "en",
            })
        self._check_html(captured, [
            ("#DC2626", "HOT badge color"),
            ("lead@buyer.com", "contact email"),
            ("mailto:lead@buyer.com", "mailto link"),
            ("#FEF3C7", "urgency callout bg"),
        ])

    @pytest.mark.asyncio
    async def test_lead_matched_delivered(self, db):
        lead_id = await _seed_lead(db, contact_email="delivered@resend.dev")
        wrapper, captured = _send_and_capture()
        with patch("resend.Emails.send", side_effect=wrapper):
            await handle_send_lead_matched_notification({
                "lead_id": lead_id,
                "lang": "en",
            })
        self._check_html(captured, [
            ("#F0F9FF", "tip callout bg"),
            ("Indoor", "facility type"),
            ("Germany", "country"),
        ])

    @pytest.mark.asyncio
    async def test_supplier_enquiry_delivered(self):
        wrapper, captured = _send_and_capture()
        with patch("resend.Emails.send", side_effect=wrapper):
            await handle_send_supplier_enquiry_email({
                "supplier_email": "delivered@resend.dev",
                "supplier_name": "PadelBuild GmbH",
                "contact_name": "Alice Smith",
                "contact_email": "alice@buyer.example",
                "message": "I need 4 courts, can you quote?",
                "lang": "en",
            })
        self._check_html(captured, [
            ("Alice Smith", "contact name"),
            ("alice@buyer.example", "contact email"),
            ("4 courts", "message content"),
        ])

    @pytest.mark.asyncio
    async def test_bounce_handled_gracefully(self):
        """Sending to bounced@resend.dev should not raise — send_email returns str|None."""
        result = await core.send_email(
            to="bounced@resend.dev",
            subject="Bounce test",
            html="<p>This should bounce.</p>",
            from_addr=core.EMAIL_ADDRESSES["transactional"],
        )
        # Resend may return success (delivery fails async) or error;
        # either way the handler must not crash.
        # send_email now returns resend_id (str) on success, None on failure.
        assert result is None or isinstance(result, str)
