# -*- coding: utf-8 -*-
"""
每日聊天汇总定时任务
- 每天 23:50 自动统计当日各店铺数据
- 用 AI 生成自然语言摘要
- 发送到企业微信 Webhook + QQ 邮件
"""

import asyncio
import os
import json
import logging
from datetime import datetime, date, timedelta
from typing import Optional

import httpx
from dotenv import load_dotenv

load_dotenv()
logger = logging.getLogger("cs_agent")

WECHAT_WEBHOOK = os.getenv("WECHAT_WEBHOOK", "")
SUMMARY_EMAIL  = os.getenv("SUMMARY_EMAIL", "")   # 收摘要的邮箱
SEND_HOUR      = int(os.getenv("SUMMARY_HOUR", "23"))
SEND_MINUTE    = int(os.getenv("SUMMARY_MINUTE", "50"))


# ──────────────────────────────────────────
# 统计数据整理
# ──────────────────────────────────────────

def _build_stats_text(target_date: str = "") -> str:
    """整理今日数据，返回给 AI 的原始统计文本"""
    from db import chat_log_db as db
    from db.deal_outcome_db import get_daily_summary

    if not target_date:
        target_date = datetime.now().strftime("%Y-%m-%d")

    stats   = db.get_daily_stats(target_date)
    convs   = db.get_daily_conversations(target_date)
    deal_sum = get_daily_summary(target_date)

    if not stats:
        return f"{target_date} 当日无任何聊天记录。"

    # 按 acc_id 分组对话片段
    conv_map: dict[str, list] = {}
    for c in convs:
        aid = c.get("acc_id") or "未知店铺"
        conv_map.setdefault(aid, []).append(c)

    lines = [f"【{target_date} 各店铺数据】\n"]

    # 成交/未成交汇总（供 AI 摘要与数据分析）
    lines.append("【成交与未成交】")
    lines.append(f"  成交：{deal_sum['成交数']} 笔，金额 {deal_sum['成交金额']:.0f} 元")
    lines.append(f"  未成交：{deal_sum['未成交数']} 笔")
    if deal_sum["未成交原因分布"]:
        for reason, cnt in deal_sum["未成交原因分布"].items():
            lines.append(f"    - {reason}：{cnt} 笔")
    if deal_sum["成交明细"]:
        for o in deal_sum["成交明细"][:5]:
            r = "让价后" if o.get("discount_given") else "直接"
            lines.append(f"    ✓ {o.get('customer_name', '')[:6]} {r}成交 {o.get('amount', 0):.0f}元")
    if deal_sum["未成交明细"]:
        for o in deal_sum["未成交明细"][:5]:
            lines.append(f"    ✗ {o.get('customer_name', '')[:6]} {o.get('reason', '')}")
    lines.append("")

    for s in stats:
        acc  = s.get("acc_id") or "未知店铺"
        plat = s.get("platform") or ""
        label = f"{acc}（{plat}）" if plat else acc

        lines.append(f"▶ 店铺：{label}")
        lines.append(f"  接待客户：{s['unique_customers']} 人，共 {s['total_msgs']} 条消息（收 {s['recv']} 发 {s['sent']}）")
        lines.append(f"  首条：{(s.get('first_msg') or '')[-8:-3]}  末条：{(s.get('last_msg') or '')[-8:-3]}")

        shop_convs = conv_map.get(acc, [])
        for c in shop_convs[:6]:   # 最多展示6个客户片段
            name = c.get("customer_name") or c.get("customer_id", "")[:8]
            snippet = (c.get("snippet") or "")[:120]
            lines.append(f"  · {name}（{c['msg_count']}条）{snippet}")
        if len(shop_convs) > 6:
            lines.append(f"  ... 还有 {len(shop_convs)-6} 位客户")
        lines.append("")

    return "\n".join(lines)


# ──────────────────────────────────────────
# AI 生成摘要
# ──────────────────────────────────────────

async def _ai_summary(raw_text: str) -> str:
    """调用 AI 把统计文本转成自然语言日报"""
    try:
        from openai import AsyncOpenAI
        client = AsyncOpenAI(
            api_key=os.getenv("OPENAI_API_KEY"),
            base_url=os.getenv("OPENAI_BASE_URL"),
        )
        model = os.getenv("OPENAI_MODEL", "doubao-seed-2-0-lite-260215")
        resp = await client.chat.completions.create(
            model=model,
            messages=[
                {
                    "role": "system",
                    "content": (
                        "你是一名电商运营助理。根据下面的客服聊天数据，"
                        "为老板写一份简洁的当日运营日报（200字以内）。"
                        "要包含：接待总人数、各店铺情况、有无成交或异常情况。"
                        "语气轻松，像发给老板的微信消息，不需要标题。"
                    ),
                },
                {"role": "user", "content": raw_text},
            ],
            max_tokens=300,
            temperature=0.5,
        )
        return resp.choices[0].message.content.strip()
    except Exception as e:
        # AI 失败就直接返回原始统计
        return raw_text


# ──────────────────────────────────────────
# 推送：企业微信
# ──────────────────────────────────────────

async def _send_wechat(content: str):
    """推送到企业微信群机器人（markdown 格式，单条 ≤4096 字节自动分段）"""
    if not WECHAT_WEBHOOK:
        logger.info("[DailySummary] 未配置 WECHAT_WEBHOOK，跳过推送")
        return

    # 企业微信单条 markdown 限 4096 字节，超长自动分段
    encoded = content.encode("utf-8")
    chunks = []
    while encoded:
        chunk = encoded[:3800].decode("utf-8", errors="ignore")
        chunks.append(chunk)
        encoded = encoded[len(chunk.encode("utf-8")):]

    async with httpx.AsyncClient(timeout=10) as client:
        for i, chunk in enumerate(chunks):
            payload = {"msgtype": "markdown", "markdown": {"content": chunk}}
            try:
                resp = await client.post(WECHAT_WEBHOOK, json=payload)
                data = resp.json()
                if data.get("errcode") == 0:
                    logger.info("[DailySummary] 企业微信推送成功（第%s段）", i + 1)
                else:
                    logger.warning("[DailySummary] 企业微信推送失败: %s", data)
            except Exception as e:
                logger.exception("[DailySummary] 企业微信推送异常: %s", e)


# ──────────────────────────────────────────
# 推送：邮件
# ──────────────────────────────────────────

def _send_email(subject: str, body: str):
    """发送日报邮件"""
    if not SUMMARY_EMAIL:
        return
    try:
        from mail.email_sender import email_sender
        import smtplib
        from email.mime.text import MIMEText
        from email.header import Header

        msg = MIMEText(body, "plain", "utf-8")
        msg["Subject"] = Header(subject, "utf-8").encode()
        msg["From"]    = f"{Header(email_sender.sender_name, 'utf-8').encode()} <{email_sender.smtp_user}>"
        msg["To"]      = SUMMARY_EMAIL

        with smtplib.SMTP(email_sender.smtp_host, email_sender.smtp_port) as s:
            s.starttls()
            s.login(email_sender.smtp_user, email_sender.smtp_password)
            s.sendmail(email_sender.smtp_user, [SUMMARY_EMAIL], msg.as_string())
        logger.info("[DailySummary] 日报邮件已发送至 %s", SUMMARY_EMAIL)
    except Exception as e:
        logger.exception("[DailySummary] 日报邮件发送失败: %s", e)


# ──────────────────────────────────────────
# 企业微信 Markdown 排版
# ──────────────────────────────────────────

def _build_wechat_markdown(title: str, ai_text: str, raw_text: str, target_date: str = "") -> str:
    """
    构建符合企业微信规范的 markdown 内容。
    支持：**bold**、<font color="...">、> 引用、``` 代码块、- 列表
    不支持：<details>、<summary>、HTML 标签（除 font/br）
    """
    from db import chat_log_db as db
    from db.deal_outcome_db import get_daily_summary
    date = target_date or datetime.now().strftime("%Y-%m-%d")
    stats = db.get_daily_stats(date)
    deal_sum = get_daily_summary(date)

    lines = [f"## {title}\n"]

    # AI 摘要部分
    lines.append("> " + ai_text.replace("\n", "\n> "))
    lines.append("")

    # 成交/未成交
    lines.append("**📈 成交与未成交**")
    lines.append(f"- 成交 **{deal_sum['成交数']}** 笔 · 金额 **{deal_sum['成交金额']:.0f}** 元")
    lines.append(f"- 未成交 **{deal_sum['未成交数']}** 笔")
    if deal_sum["未成交原因分布"]:
        for reason, cnt in deal_sum["未成交原因分布"].items():
            lines.append(f"  - {reason}：{cnt} 笔")
    lines.append("")

    # 各店铺数据表格（企业微信不支持 | 表格，用列表代替）
    if stats:
        lines.append("**📋 各店铺明细**")
        for s in stats:
            acc   = s.get("acc_id") or "未知店铺"
            plat  = s.get("platform") or ""
            label = f"{acc}（{plat}）" if plat else acc
            first = (s.get("first_msg") or "")[-8:-3]
            last  = (s.get("last_msg")  or "")[-8:-3]
            lines.append(
                f"- <font color=\"info\">{label}</font>  "
                f"接待 **{s['unique_customers']}** 人 · "
                f"消息 {s['total_msgs']} 条（收{s['recv']}/发{s['sent']}）"
                f"  {first}~{last}"
            )
    lines.append("")
    lines.append(f"<font color=\"comment\">发送时间：{datetime.now().strftime('%H:%M:%S')}</font>")

    return "\n".join(lines)


# ──────────────────────────────────────────
# 主入口：生成并推送日报
# ──────────────────────────────────────────

async def send_daily_summary(target_date: str = ""):
    """生成并推送当日汇总"""
    if not target_date:
        target_date = datetime.now().strftime("%Y-%m-%d")

    logger.info("[DailySummary] 开始生成 %s 日报...", target_date)

    raw_text = _build_stats_text(target_date)
    ai_text  = await _ai_summary(raw_text)
    title    = f"📊 {target_date} 客服日报"

    # ── 企业微信 markdown（不支持 <details>，用标准语法）──
    wechat_md = _build_wechat_markdown(title, ai_text, raw_text, target_date)
    await _send_wechat(wechat_md)

    # ── 邮件：纯文本 ──
    email_body = f"{ai_text}\n\n{'='*40}\n\n{raw_text}"
    _send_email(title, email_body)

    logger.info("[DailySummary] 日报推送完成")
    return ai_text


# ──────────────────────────────────────────
# 定时调度（由 websocket_client 启动）
# ──────────────────────────────────────────

async def scheduler():
    """每天 SEND_HOUR:SEND_MINUTE 触发日报"""
    logger.info("[DailySummary] 定时日报已启动，发送时间 %02d:%02d", SEND_HOUR, SEND_MINUTE)
    sent_today: Optional[str] = None   # 记录已发日期，防重复

    while True:
        now  = datetime.now()
        today = now.strftime("%Y-%m-%d")

        if now.hour == SEND_HOUR and now.minute == SEND_MINUTE and sent_today != today:
            sent_today = today
            try:
                await send_daily_summary(today)
            except Exception as e:
                logger.exception("[DailySummary] 日报生成出错: %s", e)

        # 每 30 秒检查一次
        await asyncio.sleep(30)


# ──────────────────────────────────────────
# 命令行手动触发
# ──────────────────────────────────────────

if __name__ == "__main__":
    import sys
    target = sys.argv[1] if len(sys.argv) > 1 else ""
    result = asyncio.run(send_daily_summary(target))
    logger.info("\n=== AI 摘要 ===")
    logger.info(result)
