import asyncio
import os
from typing import Any


def cancel_auto_quote_task(client, key: str, reason: str = ""):
    task = client._auto_quote_tasks.get(key)
    if task and not task.done():
        task.cancel()
        client._activity_log("auto_quote_cancel", key=key, reason=reason or "unknown")


def build_auto_quote_signature(state: Any) -> str:
    """为待报价内容生成稳定签名，用于避免同一批内容反复自动触发。"""
    urls = list(getattr(state, "pending_image_urls", []) or [])
    reqs = list(getattr(state, "pending_requirements", []) or [])
    req_tail = reqs[-6:] if len(reqs) > 6 else reqs
    return "||".join(urls) + "##" + "||".join(req_tail)


async def schedule_auto_quote(client, data: dict, *, shop_type_resolver):
    """
    智能兜底：客户发图后若长时间不再补充消息，自动触发一次报价，避免会话卡住。
    """
    if not client.enable_agent or not client.agent:
        return
    try:
        shop_type = shop_type_resolver(data.get('acc_id', ''), client.to_chinese(data.get('goods_name', '') or ''))
        if shop_type != "find_image":
            return
        cid = data.get('from_id', '')
        key = client._customer_key(data)
        state = client.agent._get_conversation_state(cid)
        if not state or not getattr(state, "pending_image_urls", None):
            cancel_auto_quote_task(client, key, reason="no_pending_images")
            client._auto_quote_done_sig.pop(key, None)
            return
        if state.quote_phase not in {"collecting", "waiting_result"}:
            return
        current_sig = build_auto_quote_signature(state)
        if current_sig and client._auto_quote_done_sig.get(key) == current_sig:
            client._activity_log(
                "auto_quote_skip_duplicate",
                key=key,
                pending_count=len(state.pending_image_urls),
            )
            return
        try:
            idle_seconds = max(8, int(os.getenv("AUTO_QUOTE_IDLE_SECONDS", "18")))
        except Exception:
            idle_seconds = 18

        cancel_auto_quote_task(client, key, reason="reschedule")

        async def _delayed_auto_quote(capture_key: str, capture_data: dict, wait_s: int, capture_sig: str):
            await asyncio.sleep(wait_s)
            async with client._get_customer_lock(capture_key):
                capture_cid = capture_data.get('from_id', '')
                st = client.agent._get_conversation_state(capture_cid)
                if not st or not st.pending_image_urls:
                    client._auto_quote_done_sig.pop(capture_key, None)
                    return
                # 内容变化时，放弃旧触发（会在新一轮消息后重新调度）。
                if build_auto_quote_signature(st) != capture_sig:
                    return
                # 标记本批次已自动触发，避免同内容循环“马上报价”。
                client._auto_quote_done_sig[capture_key] = capture_sig
                # 直接置为可报价，走内部自动报价入口（不伪造客户语句）。
                client.agent._mark_quote_ready(st)
                client.agent._sync_pending_quote_state(capture_cid, st)
                client._activity_log(
                    "auto_quote_trigger",
                    key=capture_key,
                    pending_count=len(st.pending_image_urls),
                    wait_s=wait_s,
                )
                notify_data = dict(capture_data)
                notify_data["msg_id"] = "auto_quote_idle_trigger"
                notify_data["msg"] = "__AUTO_QUOTE_INTERNAL_TRIGGER__"
                notify_msg = client._build_customer_message(notify_data)
                response = await client.agent.build_auto_quote_reply(st, notify_msg)
                if response.should_reply and response.reply and not response.need_transfer:
                    await client.send_reply(capture_data, response.reply)
                    client._activity_log(
                        "auto_quote_sent",
                        key=capture_key,
                        reply=response.reply,
                    )

        task = asyncio.create_task(_delayed_auto_quote(key, dict(data), idle_seconds, current_sig))
        client._auto_quote_tasks[key] = task
        client._activity_log(
            "auto_quote_scheduled",
            key=key,
            pending_count=len(state.pending_image_urls),
            phase=state.quote_phase,
            wait_s=idle_seconds,
        )
    except Exception as e:
        client._activity_log("auto_quote_schedule_error", error=str(e), key=client._customer_key(data))
