import asyncio
import time
from datetime import datetime


def fire_and_forget(client, coro):
    """后台执行协程，不阻塞接收循环；异常会记录到日志。"""
    task = asyncio.create_task(coro)

    def _done(t):
        if t.cancelled():
            return
        exc = t.exception()
        if exc:
            client.logger.exception(f"后台任务异常: {exc}")

    task.add_done_callback(_done)


def prune_seen(seen: dict, now_mono: float, ttl_sec: float = 8.0):
    if len(seen) <= 2000:
        return
    stale = [k for k, t in seen.items() if (now_mono - t) > ttl_sec]
    for k in stale:
        seen.pop(k, None)


def log_inbound_once(client, data: dict, chat_log_fn):
    """统一记录入站消息，短窗口去重，避免多分支重复写库。"""
    try:
        cid = data.get("from_id", "")
        if not cid:
            return
        msg = client.to_chinese(data.get("msg", "") or "")
        acc_id = data.get("acc_id", "")
        mtype = int(data.get("msg_type", 0) or 0)
        now_mono = time.monotonic()
        sig = f"{acc_id}|{cid}|{mtype}|{msg}"
        last = client._inbound_log_seen.get(sig, 0.0)
        if (now_mono - last) < 2.0:
            return
        client._inbound_log_seen[sig] = now_mono
        prune_seen(client._inbound_log_seen, now_mono, ttl_sec=8.0)
        chat_log_fn(
            cid,
            msg,
            "in",
            customer_name=client.to_chinese(data.get("from_name", "") or data.get("cy_name", "")),
            acc_id=acc_id,
            platform=data.get("acc_type", ""),
            msg_type=mtype,
        )
    except Exception:
        client.logger.debug("入站消息写库失败", exc_info=True)


def log_outbound_once(client, original_msg: dict, reply_content: str, chat_log_fn):
    """统一记录出站消息，短窗口去重，避免重复写库。"""
    try:
        cid = original_msg.get("from_id", "")
        if not cid:
            return
        msg = reply_content or ""
        acc_id = original_msg.get("acc_id", "")
        now_mono = time.monotonic()
        sig = f"{acc_id}|{cid}|0|{msg}"
        last = client._outbound_log_seen.get(sig, 0.0)
        if (now_mono - last) < 2.0:
            return
        client._outbound_log_seen[sig] = now_mono
        prune_seen(client._outbound_log_seen, now_mono, ttl_sec=8.0)
        chat_log_fn(
            cid,
            msg,
            "out",
            customer_name=client.to_chinese(original_msg.get("from_name", "") or original_msg.get("cy_name", "")),
            acc_id=acc_id,
            platform=original_msg.get("acc_type", ""),
            msg_type=0,
        )
    except Exception:
        client.logger.debug("出站消息写库失败", exc_info=True)


def build_customer_message(client, data: dict, customer_message_cls):
    """把原始消息字典转换为 Agent 输入模型。"""
    return customer_message_cls(
        msg_id=data.get("msg_id", ""),
        acc_id=data.get("acc_id", ""),
        msg=client.to_chinese(data.get("msg", "")),
        from_id=data.get("from_id", ""),
        from_name=client.to_chinese(data.get("from_name", "")),
        cy_id=data.get("cy_id", ""),
        acc_type=data.get("acc_type", ""),
        msg_type=data.get("msg_type", 0),
        cy_name=client.to_chinese(data.get("cy_name", "")),
        goods_name=client.to_chinese(data.get("goods_name", "")) if data.get("goods_name") else None,
        goods_order=client.to_chinese(data.get("goods_order", "")) if data.get("goods_order") else None,
    )


def touch_customer_last_contact(client, customer_id: str, db):
    """兜底更新客户最后联系时间。"""
    if not customer_id:
        return
    try:
        profile = db.get_customer(customer_id)
        profile.last_contact = datetime.now().isoformat()
        db.save_customer(profile)
    except Exception:
        client.logger.debug("更新客户最后联系时间失败: customer_id=%s", customer_id, exc_info=True)


def push_chat_to_wechat_safe(client, *, data: dict, customer_msg: str, reply_msg: str, tag: str, goods_name: str = ""):
    """异步推送企微聊天日志，失败不影响主流程。"""
    try:
        from utils.wechat_chat_log import push_chat_to_wechat

        asyncio.create_task(push_chat_to_wechat(
            customer_name=client.to_chinese(data.get("from_name", "") or data.get("cy_name", "")),
            customer_id=data.get("from_id", ""),
            acc_id=data.get("acc_id", ""),
            customer_msg=client.to_chinese(customer_msg or ""),
            reply_msg=reply_msg or "",
            goods_name=goods_name or client.to_chinese(data.get("goods_name", "") or ""),
        ))
    except Exception:
        client.logger.debug("推送企微聊天日志失败(%s)", tag, exc_info=True)
