"""A tenant's connected Mailchimp account, and sending through it.

The connection is written by the dashboard's Mailchimp connect flow into the
tenant's own schema -- the same galaxiq_tenants database and per-tenant
`integrations` table that strategist_settings lives beside (see
app/services/infra/database.py's get_setting). This is deliberately NOT
app/services/integrations/platform.py: that module reads/writes a
differently-shaped `integrations` table in the separate galaxiq_master
database, used today only for this backend's own Shopify OAuth writes. A
tenant connecting Mailchimp, Facebook, Pinterest, etc. through the dashboard
never touches that table -- it lands here instead.
"""
import logging

import httpx
from psycopg2 import sql

from app.services.infra.database import get_db_connection

logger = logging.getLogger(__name__)

MANDRILL_SEND_URL = "https://mandrillapp.com/api/1.0/messages/send.json"


def get_mailchimp_connection(tenant_id: str):
    """This tenant's active Mailchimp connection, or None.

    Returns {"transactional_api_key", "from_email", "from_name"} -- everything
    send_via_mandrill needs. None covers every reason it cannot be used: no
    connection, a disconnected/revoked one, or a connection made before SMS
    Mode existed that never captured a transactional key.
    """
    try:
        conn = get_db_connection()
    except Exception as ex:
        logger.error(f"Could not read the Mailchimp connection for {tenant_id}: {ex}")
        return None

    try:
        with conn.cursor() as cur:
            cur.execute(
                sql.SQL("SELECT metadata, status FROM {}.integrations "
                        "WHERE provider = 'mailchimp'")
                .format(sql.Identifier(tenant_id)))
            row = cur.fetchone()
    except Exception as ex:
        logger.error(f"Could not read the Mailchimp connection for {tenant_id}: {ex}")
        return None
    finally:
        conn.close()

    if not row or row[1] != "ACTIVE":
        return None

    metadata = row[0] or {}
    # The dashboard's "Transactional API Key" field lands here -- confusingly
    # nested under "sms" because it was added alongside SMS support, but
    # Mandrill's transactional email API uses the same key.
    api_key = (metadata.get("sms") or {}).get("transactionalApiKey")
    if not api_key:
        return None

    return {
        "transactional_api_key": api_key,
        # The dashboard's own "From Email" field is not in the metadata this
        # tenant saved; the account's own address is Mandrill-verified by
        # construction (it is how the account authenticated), so it is the
        # only address guaranteed to be sendable.
        "from_email": metadata.get("email") or "",
        "from_name": metadata.get("accountName") or "",
    }


def send_via_mandrill(connection: dict, to_address: str, subject: str,
                      text: str, html: str, reply_to: str = None) -> dict:
    """Send one email through Mailchimp Transactional (Mandrill).

    Never raises for a delivery failure -- mirrors send_email's own contract,
    since this is one of its branches. Error details are deliberately generic
    (no vendor name, no Mandrill reject reason): the chat model relays a tool
    error's detail straight into what it tells the customer, and neither is
    something a customer waiting on an email should see.
    """
    message = {
        "from_email": connection["from_email"],
        "from_name": connection["from_name"] or None,
        "to": [{"email": to_address, "type": "to"}],
        "subject": subject,
        "text": text,
        "html": html,
    }
    if reply_to:
        message["headers"] = {"Reply-To": reply_to}

    payload = {"key": connection["transactional_api_key"], "message": message}
    try:
        response = httpx.post(MANDRILL_SEND_URL, json=payload, timeout=20)
        response.raise_for_status()
        results = response.json()
    except Exception as ex:
        logger.error(f"Mandrill send to {to_address} failed: {ex}", exc_info=True)
        return {"status": "error", "detail": "Could not send the email."}

    # Mandrill returns 200 with a per-recipient status even for a rejection --
    # HTTP success alone does not mean the email went anywhere.
    outcome = results[0] if results else {}
    if outcome.get("status") not in ("sent", "queued", "scheduled"):
        reason = outcome.get("reject_reason") or outcome.get("status") or "rejected"
        logger.error(f"Mandrill rejected email to {to_address}: {reason}")
        return {"status": "error", "detail": "Could not send the email."}

    logger.info(f"MAILCHIMP EMAIL SENT | to={to_address} | subject={subject!r}")
    return {"status": "sent", "to": to_address, "subject": subject}
