"""
聊天记录查看器
用法:
  python scripts/chat_log_viewer.py              # 列出所有客户
  python scripts/chat_log_viewer.py <客户ID>     # 查看某客户全部对话
  python scripts/chat_log_viewer.py -s <关键词>  # 全局搜索
  python scripts/chat_log_viewer.py -t <客户ID>  # 只看今天
  python scripts/chat_log_viewer.py -l           # 实时监听最新消息（10条/刷新）
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

import time
import os
from datetime import datetime

# 强制 UTF-8 输出（Windows 终端需要）
if sys.stdout.encoding and sys.stdout.encoding.lower() != "utf-8":
    import io
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
    sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")

from db import chat_log_db as db

# ========== ANSI 颜色 ==========
try:
    import ctypes
    ctypes.windll.kernel32.SetConsoleMode(ctypes.windll.kernel32.GetStdHandle(-11), 7)
except Exception:
    pass

RESET  = "\033[0m"
BOLD   = "\033[1m"
DIM    = "\033[2m"
GREEN  = "\033[32m"
CYAN   = "\033[36m"
YELLOW = "\033[33m"
BLUE   = "\033[34m"
MAGENTA= "\033[35m"
RED    = "\033[31m"
WHITE  = "\033[97m"
BG_DARK= "\033[48;5;236m"


def clear():
    os.system("cls" if os.name == "nt" else "clear")


def header(text: str):
    width = 60
    print(f"\n{BOLD}{CYAN}{'─' * width}{RESET}")
    print(f"{BOLD}{CYAN}  {text}{RESET}")
    print(f"{BOLD}{CYAN}{'─' * width}{RESET}\n")


def fmt_time(ts: str) -> str:
    """缩短时间戳显示"""
    today = datetime.now().strftime("%Y-%m-%d")
    if ts.startswith(today):
        return ts[11:16]   # 只显示 HH:MM
    return ts[:16]


def platform_badge(platform: str) -> str:
    badges = {
        "AliWorkbench": f"{YELLOW}[淘宝]{RESET}",
        "taobao":       f"{YELLOW}[淘宝]{RESET}",
        "pinduoduo":    f"{RED}[拼多多]{RESET}",
        "jd":           f"{RED}[京东]{RESET}",
        "wechat":       f"{GREEN}[微信]{RESET}",
        "email":        f"{BLUE}[邮件]{RESET}",
    }
    return badges.get(platform, f"{DIM}[{platform}]{RESET}" if platform else "")


def print_bubble(direction: str, message: str, ts: str):
    """打印聊天气泡"""
    time_str = fmt_time(ts)
    lines = []
    if "#*#" in (message or ""):
        parts = [p.strip() for p in message.split("#*#") if p.strip()]
        if parts:
            lines = parts
    if not lines:
        lines = (message or "").split("\n")

    if direction == "in":   # 客户来消息 → 左对齐
        print(f"  {DIM}{time_str}{RESET}  {WHITE}买家{RESET}")
        for line in lines:
            print(f"  {BG_DARK} {line} {RESET}")
    else:                   # 客服回复 → 右对齐（缩进）
        print(f"  {DIM}{time_str}{RESET}  {GREEN}客服{RESET}")
        for line in lines:
            print(f"    {GREEN}> {line}{RESET}")
    print()


def cmd_list_customers():
    """列出所有客户"""
    customers = db.get_customers(limit=100)
    if not customers:
        print(f"{YELLOW}暂无聊天记录。{RESET}")
        return

    header(f"客户列表  共 {len(customers)} 人")
    print(f"  {'#':<4} {'客户ID':<24} {'姓名':<12} {'平台':<10} {'消息数':>6}  {'最后活跃'}")
    print(f"  {'─'*4} {'─'*24} {'─'*12} {'─'*10} {'─'*6}  {'─'*16}")
    for i, c in enumerate(customers, 1):
        badge = platform_badge(c.get("platform", ""))
        name  = (c.get("customer_name") or "")[:10]
        cid   = c["customer_id"]
        total = c["total_msgs"]
        last  = c.get("last_time", "")[:16]
        print(f"  {i:<4} {CYAN}{cid:<24}{RESET} {name:<12} {badge:<18} {total:>6}条  {DIM}{last}{RESET}")

    print(f"\n{DIM}用法：python chat_log_viewer.py <客户ID>{RESET}\n")


def cmd_show_conversation(customer_id: str, today_only: bool = False):
    """显示某客户对话"""
    if today_only:
        messages = db.get_conversation_today(customer_id)
        title = f"今日对话  {customer_id}"
    else:
        messages = db.get_conversation(customer_id, limit=300)
        title = f"对话记录  {customer_id}"

    if not messages:
        print(f"{YELLOW}该客户暂无记录：{customer_id}{RESET}")
        return

    header(f"{title}  （{len(messages)} 条）")

    last_date = ""
    for m in messages:
        ts = m.get("timestamp", "")
        date = ts[:10]
        if date != last_date:
            print(f"  {DIM}{'─'*20} {date} {'─'*20}{RESET}")
            last_date = date
        print_bubble(m["direction"], m["message"], ts)

    print(f"{DIM}  ── 以上共 {len(messages)} 条 ──{RESET}\n")


def cmd_search(keyword: str, customer_id: str = None):
    """搜索关键词"""
    results = db.search_messages(keyword, customer_id=customer_id, limit=50)
    title = f"搜索 [{keyword}]"
    if customer_id:
        title += f"  客户：{customer_id}"
    header(f"{title}  共 {len(results)} 条")

    if not results:
        print(f"{YELLOW}未找到包含 [{keyword}] 的消息。{RESET}")
        return

    last_cid = ""
    for r in results:
        cid = r["customer_id"]
        if cid != last_cid:
            print(f"  {CYAN}{cid}{RESET}  {r.get('customer_name','')}")
            last_cid = cid
        direction = "买家" if r["direction"] == "in" else "客服"
        color = WHITE if r["direction"] == "in" else GREEN
        # 高亮关键词
        msg = r["message"].replace(keyword, f"{RED}{BOLD}{keyword}{RESET}{color}")
        print(f"    {DIM}{r['timestamp'][:16]}{RESET}  {color}[{direction}] {msg}{RESET}")
    print()


def cmd_live(refresh: int = 3):
    """实时监听最新消息"""
    header("实时消息监听  Ctrl+C 退出")
    seen_ids = set()

    try:
        while True:
            rows = db.get_latest_messages(20)
            new_rows = [r for r in rows if r["id"] not in seen_ids]
            if new_rows:
                new_rows.reverse()
                for r in new_rows:
                    seen_ids.add(r["id"])
                    cid = r["customer_id"]
                    name = r.get("customer_name") or ""
                    label = f"{CYAN}{cid}{RESET}" + (f" {DIM}({name}){RESET}" if name else "")
                    print(f"\n{label}")
                    print_bubble(r["direction"], r["message"], r["timestamp"])
            else:
                print(f"\r  {DIM}等待新消息... {datetime.now().strftime('%H:%M:%S')}{RESET}", end="", flush=True)

            time.sleep(refresh)
    except KeyboardInterrupt:
        print(f"\n{DIM}已退出监听。{RESET}")


def _extract_urls(msg: str) -> list:
    if not msg:
        return []
    parts = [p.strip() for p in msg.split("#*#") if p.strip()]
    urls = []
    for p in parts:
        if p.startswith("http://") or p.startswith("https://"):
            urls.append(p)
    if not urls and ("http://" in msg or "https://" in msg):
        import re as _re
        tokens = _re.findall(r'(https?://\S+)', msg)
        for t in tokens:
            tl = t.lower()
            if any(ext in tl for ext in [".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp"]):
                urls.append(t)
    return urls


def _msg_refers_images(msg: str) -> bool:
    if not msg:
        return False
    refs = ("图一", "图二", "第一张", "第二张", "这张", "那张", "上面那张", "下面那张", "刚才那张", "上一张", "下一张")
    return any(r in msg for r in refs)


def _parse_ts(ts: str):
    try:
        from datetime import datetime as _dt
        return _dt.fromisoformat(ts.replace("Z",""))
    except Exception:
        return None


def analyze_conversation(messages: list) -> list:
    issues = []
    n = len(messages)
    for i, m in enumerate(messages):
        msg = m.get("message") or ""
        dir = m.get("direction")
        ts  = _parse_ts(m.get("timestamp",""))
        # 图片后未及时回复
        if dir == "in" and _extract_urls(msg):
            replied = False
            delay_ok = True
            for j in range(i+1, min(i+6, n)):
                mj = messages[j]
                if mj.get("direction") == "out":
                    replied = True
                    tsj = _parse_ts(mj.get("timestamp",""))
                    if ts and tsj and (tsj - ts).total_seconds() > 180:
                        delay_ok = False
                    break
            if not replied:
                issues.append("图片消息后未回复")
            elif not delay_ok:
                issues.append("图片消息后回复延迟超过3分钟")
        # 引用图片但找不到历史图片
        if dir == "in" and _msg_refers_images(msg):
            has_prev_img = False
            for k in range(max(0, i-10), i):
                if messages[k].get("direction") == "in" and _extract_urls(messages[k].get("message","")):
                    has_prev_img = True
                    break
            if not has_prev_img:
                issues.append("引用图片但历史中未找到对应图片")
        # 订单后未确认/引导
        if dir == "in" and ("买家已付款" in msg or "[系统订单信息]" in msg):
            confirmed = False
            for j in range(i+1, min(i+6, n)):
                if messages[j].get("direction") == "out":
                    confirmed = True
                    break
            if not confirmed:
                issues.append("订单消息后未进行确认或引导付款")
        # 合成需求未报价格
        if dir == "in" and any(k in msg for k in ("抓到", "放到", "合成", "融合", "嵌到", "替换", "P到", "抠出来放到")):
            priced = False
            for j in range(i+1, min(i+6, n)):
                mj = messages[j]
                if mj.get("direction") == "out":
                    rm = mj.get("message","")
                    if "元" in rm:
                        priced = True
                    break
            if not priced:
                issues.append("客户提出合成需求但未给出价格")
    # 去重
    dedup = []
    seen = set()
    for it in issues:
        if it not in seen:
            seen.add(it)
            dedup.append(it)
    return dedup


def cmd_analyze_all():
    customers = db.get_customers(limit=200)
    if not customers:
        print(f"{YELLOW}暂无聊天记录。{RESET}")
        return
    header("聊天记录上下文分析")
    total_issues = 0
    for c in customers:
        cid = c["customer_id"]
        msgs = db.get_conversation(cid, limit=500)
        issues = analyze_conversation(msgs)
        if issues:
            total_issues += len(issues)
            print(f"{CYAN}{cid}{RESET}  {c.get('customer_name','')}")
            for s in issues:
                print(f"  - {RED}{s}{RESET}")
            print()
    if total_issues == 0:
        print(f"{GREEN}未发现明显异常。{RESET}")
    else:
        print(f"{YELLOW}共发现 {total_issues} 项问题（按客户汇总）。{RESET}")


def print_help():
    print(f"""
{BOLD}聊天记录查看器{RESET}

  {CYAN}python chat_log_viewer.py{RESET}              列出所有客户
  {CYAN}python chat_log_viewer.py <客户ID>{RESET}     查看该客户全部对话
  {CYAN}python chat_log_viewer.py -t <客户ID>{RESET}  只看今天的对话
  {CYAN}python chat_log_viewer.py -s <关键词>{RESET}  全局搜索
  {CYAN}python chat_log_viewer.py -l{RESET}           实时监听新消息
  {CYAN}python chat_log_viewer.py -a{RESET}           分析上下文，输出异常项
  {CYAN}python chat_log_viewer.py -h{RESET}           显示帮助
""")


if __name__ == "__main__":
    args = sys.argv[1:]

    if not args:
        cmd_list_customers()

    elif args[0] in ("-h", "--help"):
        print_help()

    elif args[0] == "-s":
        keyword = args[1] if len(args) > 1 else ""
        if not keyword:
            print(f"{RED}请提供搜索关键词：python chat_log_viewer.py -s <关键词>{RESET}")
        else:
            cmd_search(keyword)

    elif args[0] == "-t":
        cid = args[1] if len(args) > 1 else ""
        if not cid:
            print(f"{RED}请提供客户ID：python chat_log_viewer.py -t <客户ID>{RESET}")
        else:
            cmd_show_conversation(cid, today_only=True)

    elif args[0] == "-l":
        cmd_live()

    elif args[0] == "-a":
        cmd_analyze_all()

    else:
        cmd_show_conversation(args[0])
