"""
Inbox Skill - Reply classification and DNC management.
"""

from __future__ import annotations
import logging
import re
from datetime import datetime
from typing import Optional

logger = logging.getLogger(__name__)


# Intent categories
INTENT_CATEGORIES = [
    "interested",       # Positive - wants to learn more
    "not_now",          # Timing isn't right
    "objection",        # Has specific concerns
    "unsubscribe",      # Wants to be removed
    "out_of_office",    # Auto-reply
    "referral",         # Refers to someone else
    "meeting_request",  # Wants to schedule
    "question",         # Has questions
    "unknown",          # Can't determine
]

# Objection types
OBJECTION_TYPES = [
    "timing",       # Bad timing
    "budget",       # No budget
    "authority",    # Not decision maker
    "need",         # No need
    "competitor",   # Using competitor
    "internal",     # Building internally
]


class InboxSkill:
    """
    Handles inbox operations:
    - Reply classification
    - Intent detection
    - DNC management
    - Next-best action suggestions
    """

    def __init__(self, config: dict):
        self.config = config
        self.settings = config.get("agents", {}).get("KINB", {}).get("settings", {})
        self.classification_threshold = self.settings.get("classification_threshold", 0.8)
        self.auto_dnc = self.settings.get("auto_dnc_unsubscribe", True)

    # -------------------------------------------------------------------------
    # Reply Classification
    # -------------------------------------------------------------------------

    def build_classification_prompt(self, reply_text: str) -> str:
        """Build prompt for LLM-based reply classification."""
        return f"""Classify this email reply into one of these categories:

CATEGORIES:
- interested: Positive response, wants to learn more, open to conversation
- meeting_request: Explicitly wants to schedule a meeting or call
- question: Has questions before making a decision
- not_now: Not interested right now, maybe later (timing issue)
- objection: Has specific concerns (budget, need, authority, competitor)
- referral: Refers to someone else to talk to
- unsubscribe: Wants to be removed, stop emails, not interested ever
- out_of_office: Automated OOO reply, vacation, leave
- unknown: Cannot determine intent

REPLY TEXT:
\"\"\"
{reply_text}
\"\"\"

Respond in this exact format:
INTENT: [category]
CONFIDENCE: [0.0-1.0]
OBJECTION_TYPE: [timing|budget|authority|need|competitor|internal|none]
MEETING_REQUESTED: [true|false]
REFERRAL_NAME: [name or none]
REFERRAL_EMAIL: [email or none]
SENTIMENT: [positive|neutral|negative]
SUMMARY: [one sentence summary]"""

    def parse_classification_response(self, response: str) -> dict:
        """Parse LLM classification response."""
        result = {
            "intent": "unknown",
            "confidence": 0.0,
            "objection_type": None,
            "meeting_requested": False,
            "referral_name": None,
            "referral_email": None,
            "sentiment": "neutral",
            "summary": "",
        }

        lines = response.strip().split("\n")
        for line in lines:
            if ":" not in line:
                continue

            key, value = line.split(":", 1)
            key = key.strip().upper()
            value = value.strip()

            if key == "INTENT":
                if value.lower() in INTENT_CATEGORIES:
                    result["intent"] = value.lower()
            elif key == "CONFIDENCE":
                try:
                    result["confidence"] = float(value)
                except ValueError:
                    pass
            elif key == "OBJECTION_TYPE":
                if value.lower() in OBJECTION_TYPES:
                    result["objection_type"] = value.lower()
                elif value.lower() != "none":
                    result["objection_type"] = value.lower()
            elif key == "MEETING_REQUESTED":
                result["meeting_requested"] = value.lower() == "true"
            elif key == "REFERRAL_NAME":
                if value.lower() != "none":
                    result["referral_name"] = value
            elif key == "REFERRAL_EMAIL":
                if value.lower() != "none":
                    result["referral_email"] = value
            elif key == "SENTIMENT":
                result["sentiment"] = value.lower()
            elif key == "SUMMARY":
                result["summary"] = value

        return result

    def classify_with_rules(self, reply_text: str) -> dict:
        """
        Rule-based classification for common patterns.
        Fast fallback when LLM isn't needed.
        """
        text_lower = reply_text.lower()

        # Out of office patterns
        ooo_patterns = [
            r"out of (the )?office",
            r"on (vacation|leave|holiday|pto)",
            r"away from (my )?(desk|email)",
            r"auto-?reply",
            r"automatic reply",
            r"i am currently out",
            r"i('m| am) away",
            r"limited access to email",
        ]
        for pattern in ooo_patterns:
            if re.search(pattern, text_lower):
                return {
                    "intent": "out_of_office",
                    "confidence": 0.95,
                    "objection_type": None,
                    "meeting_requested": False,
                    "sentiment": "neutral",
                }

        # Unsubscribe patterns
        unsub_patterns = [
            r"unsubscribe",
            r"remove (me|my email)",
            r"stop (emailing|contacting)",
            r"take me off",
            r"don'?t (email|contact) me",
            r"not interested",
            r"no thanks",
            r"please stop",
        ]
        for pattern in unsub_patterns:
            if re.search(pattern, text_lower):
                return {
                    "intent": "unsubscribe",
                    "confidence": 0.9,
                    "objection_type": None,
                    "meeting_requested": False,
                    "sentiment": "negative",
                }

        # Meeting request patterns
        meeting_patterns = [
            r"let'?s (schedule|set up|book)",
            r"(schedule|book) a (call|meeting|time)",
            r"when (are you|works|can we)",
            r"how about (tuesday|wednesday|thursday|monday|friday)",
            r"send (me )?(a |some )?times",
            r"calendly",
            r"here'?s my calendar",
        ]
        for pattern in meeting_patterns:
            if re.search(pattern, text_lower):
                return {
                    "intent": "meeting_request",
                    "confidence": 0.85,
                    "objection_type": None,
                    "meeting_requested": True,
                    "sentiment": "positive",
                }

        # Interested patterns
        interested_patterns = [
            r"(sounds|looks) (good|great|interesting)",
            r"tell me more",
            r"i'?d (like|love) to (learn|hear|know)",
            r"interested",
            r"yes,? please",
            r"let'?s (talk|chat|connect)",
        ]
        for pattern in interested_patterns:
            if re.search(pattern, text_lower):
                return {
                    "intent": "interested",
                    "confidence": 0.8,
                    "objection_type": None,
                    "meeting_requested": False,
                    "sentiment": "positive",
                }

        # Not now patterns
        not_now_patterns = [
            r"not (the )?right time",
            r"bad timing",
            r"maybe (later|next)",
            r"reach out (again )?(in|next)",
            r"check back",
            r"busy (right now|at the moment)",
            r"not (a )?priorit",
        ]
        for pattern in not_now_patterns:
            if re.search(pattern, text_lower):
                return {
                    "intent": "not_now",
                    "confidence": 0.8,
                    "objection_type": "timing",
                    "meeting_requested": False,
                    "sentiment": "neutral",
                }

        # No match - needs LLM
        return None

    # -------------------------------------------------------------------------
    # DNC Management
    # -------------------------------------------------------------------------

    def should_add_to_dnc(self, intent: str) -> bool:
        """Check if intent requires adding to DNC."""
        return intent == "unsubscribe"

    def get_dnc_reason(self, intent: str, objection_type: str = None) -> str:
        """Get reason for DNC based on intent."""
        reasons = {
            "unsubscribe": "Requested unsubscribe",
            "objection": f"Objection: {objection_type or 'unspecified'}",
        }
        return reasons.get(intent, "Manual DNC")

    # -------------------------------------------------------------------------
    # Next Best Action
    # -------------------------------------------------------------------------

    def suggest_next_action(self, classification: dict) -> dict:
        """
        Suggest next action based on reply classification.

        Returns:
            {"action": str, "priority": str, "details": str}
        """
        intent = classification.get("intent", "unknown")
        objection = classification.get("objection_type")

        actions = {
            "interested": {
                "action": "schedule_meeting",
                "priority": "high",
                "details": "Send calendar link or propose times",
            },
            "meeting_request": {
                "action": "send_calendar",
                "priority": "high",
                "details": "Immediately send available times",
            },
            "question": {
                "action": "answer_and_advance",
                "priority": "high",
                "details": "Answer questions, then propose next step",
            },
            "referral": {
                "action": "contact_referral",
                "priority": "medium",
                "details": f"Reach out to {classification.get('referral_name', 'referral')}",
            },
            "not_now": {
                "action": "schedule_follow_up",
                "priority": "low",
                "details": "Add to nurture sequence, follow up in 30-60 days",
            },
            "objection": {
                "action": "handle_objection",
                "priority": "medium",
                "details": f"Address {objection} objection with relevant response",
            },
            "unsubscribe": {
                "action": "remove_from_sequences",
                "priority": "high",
                "details": "Add to DNC, remove from all active sequences",
            },
            "out_of_office": {
                "action": "pause_sequence",
                "priority": "low",
                "details": "Pause until return date, then resume",
            },
            "unknown": {
                "action": "manual_review",
                "priority": "medium",
                "details": "Review reply manually and decide next step",
            },
        }

        return actions.get(intent, actions["unknown"])

    # -------------------------------------------------------------------------
    # Bounce Detection
    # -------------------------------------------------------------------------

    def detect_bounce(self, email_content: str) -> dict:
        """
        Detect if an email is a bounce notification.

        Returns:
            {"is_bounce": bool, "bounce_type": str|None, "reason": str|None}
        """
        text_lower = email_content.lower()

        # Hard bounce patterns
        hard_bounce_patterns = [
            r"user unknown",
            r"does not exist",
            r"invalid (recipient|address|mailbox)",
            r"no such user",
            r"recipient rejected",
            r"mailbox not found",
            r"undeliverable",
            r"550 5\.1\.1",
            r"550 user",
        ]

        for pattern in hard_bounce_patterns:
            if re.search(pattern, text_lower):
                return {
                    "is_bounce": True,
                    "bounce_type": "hard",
                    "reason": "Invalid recipient",
                }

        # Soft bounce patterns
        soft_bounce_patterns = [
            r"mailbox full",
            r"over quota",
            r"temporarily rejected",
            r"try again later",
            r"service unavailable",
            r"450 4\.2\.2",
            r"452 4\.2\.2",
        ]

        for pattern in soft_bounce_patterns:
            if re.search(pattern, text_lower):
                return {
                    "is_bounce": True,
                    "bounce_type": "soft",
                    "reason": "Temporary delivery failure",
                }

        return {"is_bounce": False, "bounce_type": None, "reason": None}
