from __future__ import annotations

import logging
from typing import TYPE_CHECKING, Any, Optional, Tuple
from core.post_ops import negotiation_strategy_reply

logger = logging.getLogger("cs_agent")

if TYPE_CHECKING:
    from core.pydantic_ai_agent import AgentDeps, ConversationState, CustomerMessage, CustomerServiceAgent


def _select_agent_by_intent(
    agent: "CustomerServiceAgent",
    message: "CustomerMessage",
    state: "ConversationState",
) -> Tuple[Optional[Any], str]:
    """
    AI 意图优先路由；识别不到时返回 (None, "intent:none")，由关键词兜底。
    """
    try:
        from utils.intent_analyzer import detect_intent

        decision = detect_intent(message.msg or "")
        intent = (decision.intent or "").strip()
        source = decision.source or "none"
        score = float(decision.score or 0.0)
    except Exception:
        intent, source, score = "", "error", 0.0

    if not intent:
        return None, "intent:none"

    if intent in ("询价", "砍价"):
        return agent.agent_pricing, f"intent:{intent}|src:{source}|score:{score:.3f}"
    if intent in ("修改", "加急"):
        return agent.agent_processing, f"intent:{intent}|src:{source}|score:{score:.3f}"
    if intent == "售后":
        return agent.agent_after_sale, f"intent:{intent}|src:{source}|score:{score:.3f}"
    if intent == "转接":
        return agent.agent_after_sale, f"intent:{intent}|src:{source}|score:{score:.3f}"
    if intent in ("打招呼", "批量", "发图"):
        target = agent.agent_after_sale if state.stage == "售后" else agent.agent
        return target, f"intent:{intent}|src:{source}|score:{score:.3f}"

    return None, f"intent:unmapped:{intent}|src:{source}|score:{score:.3f}"


def select_target_agent(agent: "CustomerServiceAgent", message: "CustomerMessage", state: "ConversationState") -> Tuple[Any, str]:
    msg_lower = message.msg.lower()
    pricing_kw = ["多少钱", "多少一张", "报价", "给个价", "几块", "价位", "能便宜点吗"]
    processing_kw = ["安排", "处理一下", "开始做", "做一下", "尽快", "加急", "付款了", "已付款"]
    similar_kw = ["有一样的", "有一样吗", "一样的吗", "类似的", "类似的吗", "同款", "相似", "类似吗"]
    order_markers = ["[系统订单信息]", "订单状态", "买家已付款"]
    risk_kw = [
        "黄色",
        "擦边",
        "色情",
        "涉黄",
        "涉政",
        "政治",
        "裸",
        "不雅",
        "天安门",
        "政治人物",
        "政治事件",
        "领导人",
        "党政",
        "习近平",
        "毛泽东",
        "邓小平",
        "江泽民",
        "胡锦涛",
        "特朗普",
        "拜登",
        "普京",
        "泽连斯基",
        "地图",
        "地形图",
        "行政区划图",
        "卫星地图",
    ]
    target_agent = agent.agent_after_sale if state.stage == "售后" else agent.agent

    ai_target, ai_reason = _select_agent_by_intent(agent, message, state)
    if ai_target is not None:
        return ai_target, ai_reason

    risk_hit = any(k in msg_lower for k in risk_kw) or agent._is_political_inquiry(message.msg) or agent._is_map_inquiry(message.msg)
    if risk_hit:
        return agent.agent_risk, "keyword:risk"
    if any(k in message.msg for k in order_markers):
        return agent.agent_order, "keyword:order"
    if any(k in msg_lower for k in processing_kw):
        return agent.agent_processing, "keyword:processing"
    if any(k in msg_lower for k in pricing_kw):
        return agent.agent_pricing, "keyword:pricing"
    if any(k in msg_lower for k in similar_kw):
        return agent.agent_similar, "keyword:similar"
    return target_agent, "fallback:default"


async def execute_ai_turn(
    agent: "CustomerServiceAgent",
    *,
    message: "CustomerMessage",
    state: "ConversationState",
    user_prompt: str,
    deps: "AgentDeps",
    history: list,
) -> str:
    target_agent, route_reason = select_target_agent(agent, message, state)
    logger.info("[路由] %s", route_reason)
    result = await target_agent.run(user_prompt, deps=deps, message_history=history)
    agent.message_histories[message.from_id] = result.all_messages()[-30:]
    reply_text = agent._colloquialize_reply(agent._normalize_reply_text(result.output))

    strategy_reply = negotiation_strategy_reply(message.msg, state)
    if strategy_reply:
        reply_text = strategy_reply

    try:
        from config.config import MIN_PRICE_FLOOR
        import re

        offer = None
        m = re.search(r"(\d{1,4})\s*(?:元|块|块钱|元钱)\b", message.msg)
        if m:
            offer = int(m.group(1))
        else:
            m2 = re.search(r"(?:能|可以|可否|能否)\s*(\d{1,4})\b", message.msg)
            offer = int(m2.group(1)) if m2 else None
        st = agent._get_conversation_state(message.from_id)
        floor = st.last_min_price if isinstance(st.last_min_price, int) and st.last_min_price > 0 else MIN_PRICE_FLOOR
        if offer is not None and offer < floor:
            reply_text = "不好意思"
    except Exception:
        pass

    try:
        from config.config import MIN_PRICE_FLOOR
        import re

        st = agent._get_conversation_state(message.from_id)
        floor = st.last_min_price if isinstance(st.last_min_price, int) and st.last_min_price > 0 else MIN_PRICE_FLOOR

        def _adjust(text: str) -> str:
            def _repl(m: Any):
                num = int(m.group(1))
                adj = max(floor, round(num / 5) * 5)
                return m.group(0).replace(str(num), str(adj))

            patterns = [
                r"按(\d{1,4})元",
                r"报价[：:]\s*(\d{1,4})\s*元",
                r"(\d{1,4})\s*元一张",
                r"打包(\d{1,4})\s*元",
            ]
            t = text
            for p in patterns:
                t = re.sub(p, _repl, t)
            return t

        reply_text = _adjust(reply_text or "")
    except Exception:
        pass

    for msg in result.new_messages():
        for part in getattr(msg, "parts", []):
            part_type = type(part).__name__
            if "ToolCall" in part_type:
                logger.info(
                    "[THINK/TOOL_CALL] %s(%s)",
                    getattr(part, "tool_name", ""),
                    getattr(part, "args", ""),
                )
            elif "ToolReturn" in part_type:
                ret = str(getattr(part, "content", ""))[:120]
                logger.info("[THINK/TOOL_RETURN] %s", ret)

    logger.info("[THINK/RAW_OUTPUT] %r", reply_text)
    return reply_text
