"""
AI lead reply generator for Canadian used car dealership.

Generates a personalized email reply to a lead who enquired about a vehicle,
grounded in the lead's info + the vehicle's facts + a dealer-edited master prompt.
Wired to Fireworks/OpenAI via an injected ai_call. Mirrors ai_descriptions.py.
"""
import json, logging, re

logger = logging.getLogger(__name__)


SMS_INSTRUCTIONS = (
    "\nTEXT MESSAGE (SMS)\n"
    "Also write a short follow-up text the dealer can send to the lead's mobile. "
    "Return it as the \"text_message\" key in the same JSON object.\n"
    "Rules:\n"
    "- Text-message tone, NOT an email: no greeting block, no formal sign-off. "
    "\"Sophie at 46 CARS INC.\" is enough.\n"
    "- 2-5 short sentences.\n"
    "- If the lead asked a question, answer it briefly first.\n"
    "- Reference the vehicle and the price (\"34,400 CAD, plus applicable taxes and licensing\" style).\n"
    "- Include this link exactly once: {sms_url}\n"
    "- No dash characters, no emojis, no ALL CAPS, no spam-trigger words (free, guaranteed, act now, limited time).\n"
    "- Vary the phrasing every time: no fixed template, no stock opening line. Style hint for this one: {hint}\n"
)


def build_lead_reply_prompt(lead, vehicle, master_prompt, dealer_name="", tracking_url="", input_data=None, sms_url="", sms_style_hint=""):
    """Build the reply-generation prompt from the lead + vehicle + master prompt.

    input_data mode (preferred): the master prompt is followed by the structured
    INPUT DATA JSON it defines (the 46_CARS contract) — no conflicting wrapper rules.
    When sms_url is given, an SMS instruction block is appended so the same call
    also returns a short follow-up text message.
    Legacy mode (input_data=None) keeps the original wrapper for backward compatibility.
    """
    if input_data is not None:
        mp = (master_prompt or "").strip() or (
            "Write a warm, professional reply to the lead about the vehicle they enquired about."
        )
        prompt = f"{mp}\n\nINPUT DATA\n{json.dumps(input_data, ensure_ascii=False, indent=2)}\n"
        if sms_url:
            prompt += SMS_INSTRUCTIONS.format(sms_url=sms_url, hint=sms_style_hint or "natural and direct")
        return prompt
    lead_name = (lead.get("name") or "").strip()
    lead_email = (lead.get("email") or "").strip()
    lead_phone = (lead.get("phone") or "").strip()
    lead_message = (lead.get("message") or "").strip()
    year = vehicle.get("year") or ""
    make = vehicle.get("make") or ""
    model = vehicle.get("model") or ""
    trim = vehicle.get("trim") or ""
    price = vehicle.get("price") or ""
    stock = vehicle.get("stock") or ""
    body_style = vehicle.get("body_style") or ""
    fuel_type = vehicle.get("fuel_type") or ""
    odometer = vehicle.get("odometer") or ""
    dealer = dealer_name or "our dealership"
    mp = (master_prompt or "").strip() or (
        "Write a warm, professional reply to the lead about the vehicle they enquired about."
    )
    lead_lines = []
    if lead_name:
        lead_lines.append(f"Lead name: {lead_name}")
    if lead_email:
        lead_lines.append(f"Lead email: {lead_email}")
    if lead_phone:
        lead_lines.append(f"Lead phone: {lead_phone}")
    if lead_message:
        lead_lines.append(f"Lead message: {lead_message}")
    lead_block = "\n".join(lead_lines) or "No lead details provided."
    return (
        f"{mp}\n\n"
        f"DEALERSHIP: {dealer} (Canada, CAD pricing, Canada-wide delivery, financing available).\n\n"
        f"VEHICLE ENQUIRED ABOUT: {year} {make} {model} {trim} | {body_style} | {fuel_type} | "
        f"Odometer: {odometer} km | Stock: {stock} | Price: {price} CAD\n\n"
        f"LEAD INFO:\n{lead_block}\n\n"
        f"LEAD TRACKING LINK (include this in the reply so the lead can view the vehicle + photos): {tracking_url or '(none provided)'}\n\n"
        f"Return JSON ONLY:\n"
        f'{{"reply_subject": "<a short email subject referencing the vehicle>", '
        f'"reply_body": "<the reply, 120-180 words, warm, Canadian English, signed off as the dealership>"}}\n\n'
        f"STRICT RULES:\n"
        f"- NO markdown, NO code fences, NO JSON fences. Raw JSON only.\n"
        f"- Use ONLY the vehicle facts above; do NOT invent specs, price, or availability.\n"
        f"- If the lead asked a question you cannot answer from the facts, give a helpful general answer and invite them to call/visit.\n"
        f"- NO USA/UK/Europe references. Canada only.\n"
        f"- reply_body must be plain text (no HTML), ready to paste into an email body.\n"
        f"- If a LEAD TRACKING LINK is provided, include it in the reply body (most leads haven't seen the photos yet).\n"
    )


def _strip_fences(raw):
    if not isinstance(raw, str):
        return raw
    s = raw.strip()
    s = re.sub(r"^```(?:json)?\s*", "", s)
    s = re.sub(r"\s*```$", "", s)
    return s.strip()


def generate_lead_reply(lead, vehicle, master_prompt, dealer_name, ai_call, tracking_url="", input_data=None, sms_url="", sms_style_hint=""):
    """Generate a reply. Returns {"status": "ok", "subject", "body", "text_message"} or {"status": "error", "error"}."""
    try:
        raw = ai_call(build_lead_reply_prompt(lead, vehicle, master_prompt, dealer_name, tracking_url, input_data=input_data, sms_url=sms_url, sms_style_hint=sms_style_hint))
    except Exception as e:
        logger.error(f"Lead reply AI call failed: {e}")
        return {"status": "error", "error": f"AI call failed: {e}"}
    try:
        data = json.loads(_strip_fences(raw))
    except Exception as e:
        return {"status": "error", "error": f"AI response was not valid JSON: {e}"}
    if not isinstance(data, dict):
        return {"status": "error", "error": "AI response was not a JSON object."}
    subject = (data.get("reply_subject") or data.get("subject") or "").strip()
    body = (data.get("reply_body") or data.get("body") or "").strip()
    if not body:
        return {"status": "error", "error": "AI returned an empty reply body."}
    text_message = (data.get("text_message") or "").strip()
    return {"status": "ok", "subject": subject, "body": body, "text_message": text_message}


SMS_ONLY_PROMPT = (
    "Write a short follow-up text message the dealer can send to the lead's mobile.\n"
    'Return JSON only: {{"text_message": "..."}}\n'
    "Rules:\n"
    "- Text-message tone, NOT an email: no greeting block, no formal sign-off. "
    "\"Sophie at 46 CARS INC.\" is enough.\n"
    "- 2-5 short sentences.\n"
    "- If the lead asked a question, answer it briefly first.\n"
    "- Reference the vehicle and the price (\"34,400 CAD, plus applicable taxes and licensing\" style).\n"
    "- Include this link exactly once: {sms_url}\n"
    "- No dash characters, no emojis, no ALL CAPS, no spam-trigger words (free, guaranteed, act now, limited time).\n"
    "- Vary the phrasing: no fixed template or stock opening. Style hint: {hint}\n"
    "\nINPUT DATA\n{input_json}\n"
)


def generate_sms_text(input_data, sms_url, style_hint, ai_call):
    """Text-only generation for leads whose email reply already exists.
    Returns {"status": "ok", "text_message"} or {"status": "error", "error"}."""
    try:
        raw = ai_call(SMS_ONLY_PROMPT.format(
            sms_url=sms_url, hint=style_hint or "natural and direct",
            input_json=json.dumps(input_data, ensure_ascii=False, indent=2),
        ))
    except Exception as e:
        logger.error(f"Lead text AI call failed: {e}")
        return {"status": "error", "error": f"AI call failed: {e}"}
    try:
        data = json.loads(_strip_fences(raw))
    except Exception as e:
        return {"status": "error", "error": f"AI response was not valid JSON: {e}"}
    text = (data.get("text_message") or "").strip() if isinstance(data, dict) else ""
    if not text:
        return {"status": "error", "error": "AI returned an empty text message."}
    return {"status": "ok", "text_message": text}
