import asyncio
import os
import time
from datetime import datetime, timedelta
import logging

logger = logging.getLogger("cs_agent")


async def unreplied_followup_loop(client):
    """定时补偿：对“最后一条是客户消息且长时间未回复”的会话，补发一次自然跟进。"""
    if not client.enable_agent or not client.agent:
        return
    while client.running:
        try:
            await asyncio.sleep(max(30, int(os.getenv("UNREPLIED_FOLLOWUP_SCAN_SECONDS", "90"))))
            await scan_and_send_unreplied_followups(client)
        except asyncio.CancelledError:
            break
        except Exception as e:
            client._activity_log("unreplied_followup_loop_error", error=str(e))


async def scan_and_send_unreplied_followups(client):
    from db import chat_log_db as cdb

    try:
        idle_minutes = max(5, int(os.getenv("UNREPLIED_FOLLOWUP_IDLE_MINUTES", "12")))
        max_age_minutes = max(idle_minutes, int(os.getenv("UNREPLIED_FOLLOWUP_MAX_AGE_MINUTES", "180")))
        followup_cd = max(300, int(os.getenv("UNREPLIED_FOLLOWUP_COOLDOWN_SECONDS", "3600")))
        limit = max(10, int(os.getenv("UNREPLIED_FOLLOWUP_LIMIT", "40")))
    except Exception:
        idle_minutes, max_age_minutes, followup_cd, limit = 12, 180, 3600, 40

    now = datetime.now()
    window_start = (now - timedelta(minutes=max_age_minutes)).strftime("%Y-%m-%d %H:%M:%S")
    conn = None
    try:
        conn = cdb._get_conn()
        rows = conn.execute(
            cdb._sql(
                """
                SELECT acc_id, customer_id, MAX(id) AS last_id
                FROM chat_logs
                WHERE timestamp >= ?
                GROUP BY acc_id, customer_id
                ORDER BY MAX(id) DESC
                LIMIT ?
                """
            ),
            (window_start, limit * 6),
        ).fetchall()
        sessions = [dict(r) for r in rows]
        sent = 0
        for s in sessions:
            if sent >= limit:
                break
            acc_id = str(s.get("acc_id", "") or "")
            cid = str(s.get("customer_id", "") or "")
            if not acc_id or not cid:
                continue
            ckey = f"{acc_id}:{cid}"
            if not client._is_owned_by_this_worker(ckey):
                continue
            last = conn.execute(
                cdb._sql(
                    """
                    SELECT id, direction, message, timestamp, customer_name, acc_id, platform
                    FROM chat_logs
                    WHERE acc_id = ? AND customer_id = ?
                    ORDER BY id DESC
                    LIMIT 1
                    """
                ),
                (acc_id, cid),
            ).fetchone()
            if not last:
                continue
            last = dict(last)
            if str(last.get("direction", "")) != "in":
                continue
            last_ts = last.get("timestamp")
            if isinstance(last_ts, datetime):
                last_dt = last_ts
            else:
                last_dt = datetime.strptime(str(last_ts)[:19], "%Y-%m-%d %H:%M:%S")
            idle_s = (now - last_dt).total_seconds()
            if idle_s < idle_minutes * 60 or idle_s > max_age_minutes * 60:
                continue
            now_mono = time.monotonic()
            if (now_mono - client._unreplied_followup_sent.get(ckey, 0.0)) < followup_cd:
                continue

            last_msg = str(last.get("message", "") or "").strip().lower()
            if last_msg in {"好的", "好", "ok", "收到", "嗯", "哦"}:
                continue

            followup = await compose_ai_scene_reply(
                client,
                original_msg={
                    "acc_id": acc_id,
                    "from_id": cid,
                    "from_name": client.to_chinese(last.get("customer_name", "") or cid),
                    "acc_type": str(last.get("platform", "") or "AliWorkbench"),
                    "msg": str(last.get("message", "") or ""),
                },
                scene="unreplied_followup",
                intent_hint="客户上一条消息还没接上，先自然承接并请对方补一句当前要处理的图或要求。",
                fallback="刚看到你消息了，我在的。你把要处理的图或要求再发我一下，我马上接着看。",
            )
            fake = {
                "acc_id": acc_id,
                "from_id": cid,
                "from_name": client.to_chinese(last.get("customer_name", "") or cid),
                "cy_id": cid,
                "cy_name": client.to_chinese(last.get("customer_name", "") or cid),
                "acc_type": str(last.get("platform", "") or "AliWorkbench"),
                "msg": str(last.get("message", "") or ""),
                "msg_type": 0,
            }
            await client.send_reply(fake, followup)
            client._unreplied_followup_sent[ckey] = now_mono
            sent += 1
            client._activity_log(
                "unreplied_followup_sent",
                acc_id=acc_id,
                customer_id=cid,
                idle_seconds=int(idle_s),
                last_msg=str(last.get("message", "") or "")[:120],
                reply=followup,
            )
    finally:
        try:
            if conn:
                conn.close()
        except Exception:
            logger.debug("关闭数据库连接失败", exc_info=True)


async def compose_ai_scene_reply(client, *, original_msg: dict, scene: str, intent_hint: str, fallback: str) -> str:
    """场景化 AI 直接生成回复（不依赖固定模板）。"""
    if not client.enable_agent or not client.agent or not client.AgentDeps:
        return fallback
    try:
        deps = client.AgentDeps(
            msg_id=str(original_msg.get("msg_id", "") or f"{scene}_gen"),
            acc_id=str(original_msg.get("acc_id", "") or ""),
            from_id=str(original_msg.get("from_id", "") or ""),
            platform=str(original_msg.get("acc_type", "") or ""),
        )
        customer_msg = client.to_chinese(str(original_msg.get("msg", "") or ""))
        prompt = (
            "你是淘宝客服，直接生成一条发给客户的话。\n"
            f"场景: {scene}\n"
            f"意图: {intent_hint}\n"
            f"客户原话: {customer_msg}\n"
            "要求: 1-2句，自然口语，不要模板腔，不要新增价格/承诺；只输出最终回复。\n"
        )
        result = await client.agent.agent_natural_reply.run(prompt, deps=deps, message_history=[])
        out = str(getattr(result, "output", "") or "").strip()
        if not out:
            return fallback
        if out.startswith("话术|") or "[转移会话]" in out or "TRANSFER_REQUESTED" in out:
            return fallback
        client._activity_log(
            "ai_scene_reply_generated",
            acc_id=str(original_msg.get("acc_id", "") or ""),
            customer_id=str(original_msg.get("from_id", "") or ""),
            scene=scene,
            generated=out[:160],
        )
        return out
    except Exception as e:
        client._activity_log(
            "ai_scene_reply_error",
            acc_id=str(original_msg.get("acc_id", "") or ""),
            customer_id=str(original_msg.get("from_id", "") or ""),
            scene=scene,
            error=str(e),
        )
        return fallback
