"""Tool: suggest_next_action — Rule-based next action advisor.

Analyzes all active campaigns and recommends the highest-priority
action. No LLM needed — purely rule-based decision tree.

Priority order:
1. Hot leads (reply ASAP)
2. Questions to answer
3. Pending approvals
4. Follow-ups due
5. Warm-up engagement for invited prospects
6. Invitations ready (warm-up complete)
7. Warm-up needed (engage before inviting)
"""

from __future__ import annotations

import logging
import time
from typing import Any

from ..config import get_tier
from ..constants import (
    FREE_MAX_FOLLOWUPS,
    MIN_WARMUP_ENGAGEMENTS,
    PRO_FOLLOWUP_SCHEDULE_DAYS,
    PRO_MAX_FOLLOWUPS,
    TIER_PRO,
)
from ..db.queries import (
    get_campaign,
    get_engagement_count_for_outreach,
    get_last_activity_timestamp,
    get_messages_for_outreach,
    get_setting,
    get_stale_outreaches,
    list_campaigns,
)
from ..db.schema import get_db
from ..formatter import stars

logger = logging.getLogger(__name__)

# Don't suggest follow-up if contacted less than this many days ago
MIN_FOLLOWUP_DAYS = 3

# For invited prospects, suggest engagement after this many days
INVITED_ENGAGE_AFTER_DAYS = 3

# Max recommendations to show
MAX_RECOMMENDATIONS = 5

# Icons for each action type
ACTION_ICONS = {
    "hot_lead": "🔥",
    "question": "❓",
    "approval": "👀",
    "followup": "💬",
    "engage_invited": "🎯",
    "invite_ready": "📤",
    "warmup": "🎯",
    "new_campaign": "🚀",
}


async def run_suggest_next_action(campaign_id: str = "") -> str:
    """Suggest the best next action for your outreach.

    Analyzes all active campaigns and recommends the highest-priority
    action: reply to hot leads, approve pending messages, send follow-ups,
    warm up prospects with engagement, or send invitations.
    """

    # ── Pre-checks ──
    setup_done = get_setting("setup_complete", False)
    if not setup_done:
        return (
            "Setup required before suggesting actions.\n\n"
            "Please run setup_profile first."
        )

    # ── Load campaigns ──
    if campaign_id:
        campaign = get_campaign(campaign_id)
        if not campaign:
            return f"Campaign not found: {campaign_id}"
        campaigns = [campaign]
    else:
        campaigns = list_campaigns(status="active")
        if not campaigns:
            return (
                "No active campaigns.\n\n"
                "Create one first: create_campaign(\"your target description\")"
            )

    tier = get_tier()
    max_followups = PRO_MAX_FOLLOWUPS if tier == TIER_PRO else FREE_MAX_FOLLOWUPS
    now = int(time.time())

    # ── Scan all outreaches across campaigns ──
    recommendations: list[dict[str, Any]] = []

    for camp in campaigns:
        cid = camp["id"]
        camp_name = camp["name"]

        db = get_db()
        outreaches = db.execute(
            """SELECT o.id as outreach_id, o.campaign_id, o.contact_id,
                      o.status, o.followup_count, o.next_action, o.updated_at,
                      c.name, c.title, c.company, c.fit_score, c.linkedin_url
               FROM outreaches o
               JOIN contacts c ON o.contact_id = c.id
               WHERE o.campaign_id = ?
                 AND o.status NOT IN ('opted_out', 'closed_happy', 'closed_unhappy', 'skipped')
               ORDER BY c.fit_score DESC""",
            (cid,),
        ).fetchall()
        db.close()

        for row in outreaches:
            r = dict(row)
            status = r["status"]
            name = r.get("name", "Unknown")
            title = r.get("title", "")
            company = r.get("company", "")
            fit_score = r.get("fit_score", 0)
            outreach_id = r["outreach_id"]
            followup_count = r.get("followup_count", 0) or 0

            role_str = title
            if company:
                role_str += f" at {company}" if role_str else company

            # Priority 1: Hot leads
            if status == "hot_lead":
                recommendations.append({
                    "priority": 1,
                    "icon": ACTION_ICONS["hot_lead"],
                    "text": f"Reply to **{name}** ({role_str}) — they're interested!",
                    "action": f"Run: reply_to_prospect(outreach_id='{outreach_id}')",
                    "fit_score": fit_score,
                    "campaign": camp_name,
                })

            # Priority 2: Questions to answer
            elif status == "replied":
                messages = get_messages_for_outreach(outreach_id)
                last_msg = messages[-1] if messages else None
                if last_msg and last_msg.get("sentiment") == "question":
                    recommendations.append({
                        "priority": 2,
                        "icon": ACTION_ICONS["question"],
                        "text": f"Answer **{name}**'s question ({role_str})",
                        "action": f"Run: reply_to_prospect(outreach_id='{outreach_id}')",
                        "fit_score": fit_score,
                        "campaign": camp_name,
                    })

            # Priority 3: Pending approvals
            elif status == "review_pending" or (r.get("next_action") and r["next_action"].strip()):
                recommendations.append({
                    "priority": 3,
                    "icon": ACTION_ICONS["approval"],
                    "text": f"Approve or skip pending message for **{name}** ({role_str})",
                    "action": "Run: approve_outreach('yes')",
                    "fit_score": fit_score,
                    "campaign": camp_name,
                })

            # Priority 4: Follow-ups due
            elif status == "connected" and followup_count < max_followups:
                last_activity = get_last_activity_timestamp(outreach_id)
                days_since = (now - last_activity) // 86400 if last_activity else 999

                # Check pro schedule
                if tier == TIER_PRO and followup_count > 0:
                    schedule_idx = min(followup_count, len(PRO_FOLLOWUP_SCHEDULE_DAYS) - 1)
                    required_days = PRO_FOLLOWUP_SCHEDULE_DAYS[schedule_idx]
                else:
                    required_days = MIN_FOLLOWUP_DAYS

                if days_since >= required_days:
                    recommendations.append({
                        "priority": 4,
                        "icon": ACTION_ICONS["followup"],
                        "text": f"Send follow-up #{followup_count + 1} to **{name}** ({role_str})",
                        "action": "Run: send_followup()",
                        "fit_score": fit_score,
                        "campaign": camp_name,
                    })

            # Priority 5: Engaged invited prospects — warm them up
            elif status == "invited":
                days_since_invite = (now - (r.get("updated_at") or 0)) // 86400
                eng_count = get_engagement_count_for_outreach(outreach_id)
                if days_since_invite >= INVITED_ENGAGE_AFTER_DAYS and eng_count < 3:
                    recommendations.append({
                        "priority": 5,
                        "icon": ACTION_ICONS["engage_invited"],
                        "text": f"Engage with **{name}**'s posts (invited {days_since_invite}d ago, warm up)",
                        "action": "Run: engage_prospect()",
                        "fit_score": fit_score,
                        "campaign": camp_name,
                    })

            # Priority 6 & 7: Pending prospects
            elif status == "pending":
                eng_count = get_engagement_count_for_outreach(outreach_id)
                if eng_count >= MIN_WARMUP_ENGAGEMENTS:
                    # Warm-up complete → ready to invite
                    recommendations.append({
                        "priority": 6,
                        "icon": ACTION_ICONS["invite_ready"],
                        "text": f"Send invitation to **{name}** ({role_str}) — warm-up complete ({eng_count} engagements)",
                        "action": "Run: generate_and_send()",
                        "fit_score": fit_score,
                        "campaign": camp_name,
                    })
                else:
                    # Needs warm-up first
                    recommendations.append({
                        "priority": 7,
                        "icon": ACTION_ICONS["warmup"],
                        "text": f"Engage with **{name}**'s posts first ({eng_count}/{MIN_WARMUP_ENGAGEMENTS} warm-up touches)",
                        "action": "Run: engage_prospect()",
                        "fit_score": fit_score,
                        "campaign": camp_name,
                    })

        # Priority 8: Close stale outreaches (no activity for 14+ days)
        stale = get_stale_outreaches(cid, stale_days=14)
        for s in stale[:3]:  # Cap at 3 stale recommendations per campaign
            recommendations.append({
                "priority": 8,
                "icon": "\u23f0",
                "text": f"**{s['name']}** has been inactive for {s['days_stale']}d \u2014 close or re-engage?",
                "action": f"close_outreach(outreach_id='{s['outreach_id']}') or send_followup()",
                "fit_score": s.get("fit_score", 0),
                "campaign": camp_name,
            })

    # ── Sort by priority, then fit_score ──
    recommendations.sort(key=lambda r: (r["priority"], -r.get("fit_score", 0)))

    if not recommendations:
        return (
            "✅ All caught up! No immediate actions needed.\n\n"
            "Your campaigns are running smoothly.\n"
            "Use show_status() for your dashboard, or\n"
            "create_campaign(\"target\") to find new prospects."
        )

    # ── Format output ──
    top = recommendations[:MAX_RECOMMENDATIONS]
    remaining = len(recommendations) - MAX_RECOMMENDATIONS

    output = ["🎯 **Recommended Next Actions:**\n"]

    for i, rec in enumerate(top, 1):
        output.append(f"{i}. {rec['icon']} {rec['text']}")
        output.append(f"   → {rec['action']}")
        if len(campaigns) > 1:
            output.append(f"   Campaign: {rec['campaign']}")
        output.append("")

    if remaining > 0:
        output.append(f"... and {remaining} more action{'s' if remaining != 1 else ''} queued.")
        output.append("")

    # ── Summary stats ──
    hot = sum(1 for r in recommendations if r["priority"] == 1)
    questions = sum(1 for r in recommendations if r["priority"] == 2)
    approvals = sum(1 for r in recommendations if r["priority"] == 3)
    followups = sum(1 for r in recommendations if r["priority"] == 4)
    warmups = sum(1 for r in recommendations if r["priority"] in (5, 7))
    ready = sum(1 for r in recommendations if r["priority"] == 6)

    summary_parts = []
    if hot:
        summary_parts.append(f"{hot} hot lead{'s' if hot != 1 else ''}")
    if questions:
        summary_parts.append(f"{questions} question{'s' if questions != 1 else ''}")
    if approvals:
        summary_parts.append(f"{approvals} pending approval{'s' if approvals != 1 else ''}")
    if followups:
        summary_parts.append(f"{followups} follow-up{'s' if followups != 1 else ''} due")
    if ready:
        summary_parts.append(f"{ready} ready to invite")
    if warmups:
        summary_parts.append(f"{warmups} need{'s' if warmups == 1 else ''} warm-up")
    stale_count = sum(1 for r in recommendations if r["priority"] == 8)
    if stale_count:
        summary_parts.append(f"{stale_count} stale lead{'s' if stale_count != 1 else ''}")

    if summary_parts:
        output.append("Summary: " + " · ".join(summary_parts))

    return "\n".join(output)
