"""内照明心复盘语录 → 交易教练点评."""
from __future__ import annotations

from typing import Any

from hub_ai.client import generate_text, model_label
from hub_ai.rolling_summary import refresh_session_rolling_summary
from hub_ai.text_util import clip_text, is_ai_error_reply
from hub_ai.config import (
    CHAT_MAX_CONTINUATIONS,
    CHAT_MAX_OUTPUT_TOKENS,
    CHAT_TEMPERATURE,
    CHAT_USER_MESSAGE_MAX_CHARS,
)
from hub_ai.prompts import CHAT_SYSTEM, build_archive_quote_review_prompt
from hub_ai.store import (
    CHAT_BOT_TRADING,
    append_chat_message,
    create_new_session,
    delete_chat_session,
    get_active_session,
    list_chat_sessions,
)
from lib.hub.hub_symbol_archive_lib import list_daily_trades


def _tag_label(tag: str) -> str:
    t = (tag or "").strip().lower()
    if t == "sick":
        return "犯病"
    if t == "emotion":
        return "情绪化"
    return t or "—"


def _fmt_pnl(v: Any) -> str:
    try:
        n = float(v or 0)
    except (TypeError, ValueError):
        return "—"
    sign = "+" if n > 0 else ""
    return f"{sign}{n:.2f}U"


def _fmt_pct(v: Any) -> str:
    try:
        n = float(v)
    except (TypeError, ValueError):
        return "—"
    return f"{n:.1f}%"


def _fmt_rr(v: Any) -> str:
    try:
        n = float(v)
    except (TypeError, ValueError):
        return "—"
    return f"{n:.2f}:1"


def format_archive_trades_for_ai(payload: dict[str, Any]) -> str:
    trades = payload.get("trades") or []
    stats = payload.get("stats") or {}
    lines = [
        (
            f"统计:开仓 {int(stats.get('open_count') or 0)} 笔,"
            f"盈利 {int(stats.get('win_count') or 0)} / 亏损 {int(stats.get('loss_count') or 0)},"
            f"平均盈利 {_fmt_pnl(stats.get('avg_win'))},平均亏损 {_fmt_pnl(stats.get('avg_loss'))},"
            f"胜率 {_fmt_pct(stats.get('win_rate'))},盈亏比 {_fmt_rr(stats.get('profit_loss_ratio'))},"
            f"最大盈利 {_fmt_pnl(stats.get('max_win'))},最大亏损 {_fmt_pnl(stats.get('max_loss'))},"
            f"犯病 {int(stats.get('sick_count') or 0)} 笔,"
            f"盈亏合计 {_fmt_pnl(stats.get('pnl_total'))},"
            f"剔除犯病盈亏 {_fmt_pnl(stats.get('pnl_ex_sick'))}"
        )
    ]
    if not trades:
        lines.append("(该日无交易记录)")
        return "\n".join(lines)
    max_rows = 50
    if len(trades) > max_rows:
        lines.append(f"(共 {len(trades)} 笔,以下展示最近 {max_rows} 笔)")
    for i, t in enumerate(trades[:max_rows], 1):
        ex = str(t.get("exchange_key") or t.get("account_exchange_key") or "—")
        sym = str(t.get("symbol") or "—")
        direction = str(t.get("direction") or "—")
        opened = str(t.get("opened_at") or "—")
        closed = str(t.get("closed_at") or "—")
        hold = str(t.get("hold_minutes_text") or t.get("hold_minutes") or "—")
        result = str(t.get("result") or "—")
        pnl = _fmt_pnl(t.get("pnl_amount"))
        entry = str(t.get("entry_type") or t.get("entry_reason") or t.get("monitor_type") or "—")
        tag = _tag_label(str(t.get("behavior_tag") or ""))
        note = clip_text(str(t.get("note") or "").strip(), 80)
        line = (
            f"{i}. {ex} | {sym} | {direction} | 开仓类型 {entry} | "
            f"开 {opened} | 平 {closed} | 持仓 {hold} | 结果 {result} | "
            f"盈亏 {pnl} | 标签 {tag}"
        )
        if note:
            line += f" | 备注 {note}"
        lines.append(line)
    return "\n".join(lines)


def send_archive_quote_review(
    *,
    quote_date: str,
    content: str,
) -> dict[str, Any]:
    text = (content or "").strip()
    if not text:
        return {"ok": False, "msg": "语录内容不能为空"}
    day = (quote_date or "").strip()[:10]
    if not day:
        return {"ok": False, "msg": "语录日期无效"}

    session = create_new_session(
        trading_day=day,
        title=f"复盘 {day}",
        bot_mode=CHAT_BOT_TRADING,
    )
    sid = session["id"]

    archive_payload = list_daily_trades(trading_day=day, period="today")
    archive_trades_text = format_archive_trades_for_ai(archive_payload)
    user_for_prompt = clip_text(text, CHAT_USER_MESSAGE_MAX_CHARS)

    user_prompt = build_archive_quote_review_prompt(
        quote_date=day,
        archive_trades_text=archive_trades_text,
        user_message=user_for_prompt,
    )
    reply = generate_text(
        system=CHAT_SYSTEM,
        user=user_prompt,
        temperature=CHAT_TEMPERATURE,
        max_tokens=CHAT_MAX_OUTPUT_TOKENS,
        max_continuations=CHAT_MAX_CONTINUATIONS,
    )
    if is_ai_error_reply(reply):
        delete_chat_session(sid)
        return {"ok": False, "msg": reply}

    append_chat_message(sid, "user", text)
    session = append_chat_message(sid, "assistant", reply)
    refresh_session_rolling_summary(
        sid,
        prior_summary="",
        user_text=text,
        assistant_text=reply,
        bot_mode=CHAT_BOT_TRADING,
    )
    session = get_active_session() or session
    return {
        "ok": True,
        "trading_day": day,
        "session": session,
        "sessions": list_chat_sessions(),
        "reply": reply,
        "model": model_label(),
    }
