"""Tool 4: check_replies — Check for new replies across all campaigns.

Fetches new LinkedIn messages, classifies sentiment
(positive/negative/question/neutral), surfaces hot leads,
and auto-handles opt-outs.
"""

from __future__ import annotations

import logging
from typing import Any

from ..ai.sentiment import classify_sentiment
from ..db.queries import (
    get_setting,
    list_campaigns,
    log_action,
    save_message,
    update_outreach,
)
from ..db.schema import get_db
from ..linkedin import (
    UnipileAuthError,
    UnipileError,
    get_account_id,
    get_linkedin_client,
)

logger = logging.getLogger(__name__)

# Sentiment display config
SENTIMENT_ICONS = {
    "positive": "🔥",
    "negative": "👎",
    "question": "❓",
    "neutral": "💬",
    "out_of_office": "✈️",
    "opt_out": "🚫",
}

SENTIMENT_ACTIONS = {
    "positive": "ACTION NEEDED: Reply with your booking link!",
    "negative": "No action needed. Outreach closed.",
    "question": "ACTION NEEDED: Answer their question.",
    "neutral": "No action needed. Monitor.",
    "out_of_office": "Will follow up when they're back.",
    "opt_out": "Auto-closed. They won't be contacted again.",
}


async def run_check_replies() -> str:
    """Check for new replies across all active campaigns.

    Flow:
    1. Fetch recent LinkedIn inbox messages
    2. Match messages to active outreach contacts
    3. Classify sentiment for new messages
    4. Handle opt-outs automatically
    5. Surface hot leads first
    """

    # ── Pre-checks ──
    setup_done = get_setting("setup_complete", False)
    if not setup_done:
        return "❌ Please run setup_profile first!"

    account_id = get_account_id()
    if not account_id:
        return "❌ No LinkedIn account connected. Run setup_profile first."

    try:
        client = get_linkedin_client()
    except UnipileError as e:
        return f"❌ {e}"

    # ── Fetch messages from LinkedIn via Unipile ──
    try:
        messages = await client.get_chats(account_id=account_id)
    except UnipileAuthError:
        await client.close()
        return (
            "🔑 LinkedIn account disconnected.\n\n"
            "Run setup_profile() again to reconnect."
        )
    except Exception as e:
        logger.error(f"Failed to check messages: {e}")
        await client.close()
        return f"❌ Failed to check LinkedIn messages: {e}"
    finally:
        await client.close()

    if not messages:
        return (
            "📭 No new messages found.\n\n"
            "Tip: Replies usually take 1-3 days after invitations are accepted.\n"
            "Use show_status to see your campaign progress."
        )

    # ── Match messages to outreach contacts ──
    db = get_db()

    # Get all outreach contacts with their LinkedIn IDs
    outreach_contacts = db.execute(
        """SELECT o.id as outreach_id, o.status, c.linkedin_id, c.name, c.title, c.company, c.campaign_id
           FROM outreaches o
           JOIN contacts c ON o.contact_id = c.id
           WHERE o.status IN ('invited', 'connected', 'messaged')"""
    ).fetchall()

    # Build lookup by linkedin_id
    contact_lookup: dict[str, dict] = {}
    for row in outreach_contacts:
        r = dict(row)
        if r.get("linkedin_id"):
            contact_lookup[r["linkedin_id"]] = r

    db.close()

    # ── Process matches ──
    matched_replies: list[dict[str, Any]] = []

    for msg in messages:
        sender_id = msg.get("sender_id", "")
        if not sender_id or sender_id not in contact_lookup:
            continue  # Message not from a campaign contact

        contact = contact_lookup[sender_id]
        reply_text = msg.get("text", "")

        # Classify sentiment
        sentiment = await classify_sentiment(reply_text)

        # Save the reply
        save_message(
            outreach_id=contact["outreach_id"],
            role="prospect",
            text=reply_text,
            sentiment=sentiment,
        )

        # Handle opt-outs
        if sentiment == "opt_out":
            update_outreach(contact["outreach_id"], status="opted_out")
            log_action("opt_out_detected", outreach_id=contact["outreach_id"],
                       details={"text": reply_text[:200]})

        # Hot lead detection
        elif sentiment == "positive":
            update_outreach(contact["outreach_id"], status="hot_lead")
            log_action("hot_lead_detected", outreach_id=contact["outreach_id"],
                       details={"text": reply_text[:200]})

        # Question — needs attention
        elif sentiment == "question":
            update_outreach(contact["outreach_id"], status="replied")

        # Other
        else:
            update_outreach(contact["outreach_id"], status="replied")

        matched_replies.append({
            "name": contact.get("name", "Unknown"),
            "title": contact.get("title", ""),
            "company": contact.get("company", ""),
            "text": reply_text,
            "sentiment": sentiment,
        })

    # ── Format output ──
    if not matched_replies:
        return (
            f"📬 Checked {len(messages)} messages — none from campaign contacts.\n\n"
            "Replies from non-campaign contacts are not tracked.\n"
            "Use show_status to see campaign progress."
        )

    # Sort: hot leads first, then questions, then rest
    priority_order = {"positive": 0, "question": 1, "neutral": 2, "negative": 3, "out_of_office": 4, "opt_out": 5}
    matched_replies.sort(key=lambda r: priority_order.get(r["sentiment"], 99))

    output = [f"📬 {len(matched_replies)} new repl{'y' if len(matched_replies) == 1 else 'ies'}:\n"]

    for i, reply in enumerate(matched_replies):
        icon = SENTIMENT_ICONS.get(reply["sentiment"], "💬")
        action = SENTIMENT_ACTIONS.get(reply["sentiment"], "")

        name = reply["name"]
        role = reply.get("title", "")
        if reply.get("company"):
            role += f" at {reply['company']}" if role else reply["company"]

        text_preview = reply["text"][:150]
        if len(reply["text"]) > 150:
            text_preview += "..."

        output.append(f"{icon} **{name}** ({role}):")
        output.append(f"   \"{text_preview}\"")
        if action:
            output.append(f"   → {action}")
        output.append("")

    # Summary
    hot_count = sum(1 for r in matched_replies if r["sentiment"] == "positive")
    question_count = sum(1 for r in matched_replies if r["sentiment"] == "question")
    opt_out_count = sum(1 for r in matched_replies if r["sentiment"] == "opt_out")

    if hot_count > 0:
        output.append(f"🔥 {hot_count} hot lead{'s' if hot_count > 1 else ''}! Reply to them ASAP.")
    if question_count > 0:
        output.append(f"❓ {question_count} question{'s' if question_count > 1 else ''} to answer.")
    if opt_out_count > 0:
        output.append(f"🚫 {opt_out_count} opt-out{'s' if opt_out_count > 1 else ''} (auto-closed).")

    return "\n".join(output)
