"""AI references 工具模块。

为 AI 输出（ai_cache.result_json / ai_messages.reference_card）
注入数据来源引用元数据，便于前端渲染可点击引用卡片。

- App2~8：通过 dispatcher._write_cache 统一注入到 result['_references']
- App1：通过 xcx_chat 在 assistant 消息写入时调用 build_app1_reference 生成单卡片
"""

from __future__ import annotations

from typing import Any


def build_app_references(app_type: str, context: dict) -> list[dict]:
    """为 App2~8 构建 references 列表，供前端消息卡片渲染。

    引用结构：
        {
          "type": "member" | "task" | "assistant" | "finance",
          "id": int | str,
          "label": "卡片上的文字",
          "link": "/pages/xxx/xxx?param=val"（小程序页面路径）,
          "source_page": 小程序页面 contextType
        }

    Args:
        app_type: 应用名称
        context: 传给 build_prompt 的上下文（含 site_id / member_id 等）

    Returns:
        refs 数组。无有效上下文时返回空数组。
    """
    refs: list[dict] = []
    site_id = context.get("site_id")
    member_id = context.get("member_id")
    assistant_id = context.get("assistant_id")
    time_dimension = context.get("time_dimension")

    if member_id is not None:
        refs.append({
            "type": "member",
            "id": member_id,
            "label": f"客户 #{member_id}",
            "link": f"/pages/customer-detail/customer-detail?customerId={member_id}",
            "source_page": "customer-detail",
        })

    if assistant_id is not None:
        refs.append({
            "type": "assistant",
            "id": assistant_id,
            "label": f"助教 #{assistant_id}",
            "link": f"/pages/coach-detail/coach-detail?coachId={assistant_id}",
            "source_page": "coach-detail",
        })

    if app_type == "app2_finance" and time_dimension:
        refs.append({
            "type": "finance",
            "id": time_dimension,
            "label": f"财务看板：{_label_for_dimension(time_dimension)}",
            "link": f"/pages/board-finance/board-finance?timeDimension={time_dimension}",
            "source_page": "board-finance",
        })

    # 保留 site_id 作为兜底上下文（不单独成卡，但用于前端场景判断）
    if site_id is not None and refs:
        for r in refs:
            r.setdefault("site_id", site_id)

    return refs


def attach_references(app_type: str, result: dict | None, context: dict) -> dict | None:
    """向 AI 输出 result 追加 _references 字段（非破坏性）。

    - result 为 None 时原样返回（调用失败不注入）
    - result 为 dict 时追加 _references 字段；如果 result 已含 _references，保留原值
    """
    if result is None or not isinstance(result, dict):
        return result
    if "_references" in result:
        return result
    refs = build_app_references(app_type, context)
    if refs:
        result["_references"] = refs
    return result


def build_app1_reference_card(source_page: str | None, context_id: int | str | None) -> dict | None:
    """为 App1（chat）assistant 消息构建单个 reference_card。

    兼容前端 chat.wxml 已有的 {type, title, summary, data, dataList} 渲染结构，
    额外携带 link 字段供前端点击跳转详情页。

    当用户在特定页面（customer-detail / coach-detail / task-detail）发起对话时，
    自动附加对应跳转卡片。普通浮窗对话（source_page='general'）返回 None。

    与 chat_service.build_reference_card 不同：本函数不查 DB，仅按 source_page 构造链接。
    """
    if not source_page or not context_id:
        return None

    mapping: dict[str, tuple[str, str, str]] = {
        "customer-detail": ("customer", "客户", "customerId"),
        "coach-detail": ("assistant", "助教", "coachId"),
        "task-detail": ("task", "任务", "taskId"),
    }
    entry = mapping.get(source_page)
    if entry is None:
        return None
    ref_type, label_prefix, param = entry

    return {
        "type": ref_type,
        "title": f"{label_prefix} #{context_id}",
        "summary": f"点击查看{label_prefix}详情",
        "data": {},
        "link": f"/pages/{source_page}/{source_page}?{param}={context_id}",
        "source_page": source_page,
    }


def _label_for_dimension(dimension: str) -> str:
    """8 个财务维度 → 中文标签。"""
    mapping = {
        "this_month": "本月",
        "last_month": "上月",
        "this_week": "本周",
        "last_week": "上周",
        "this_quarter": "本季度",
        "last_quarter": "上季度",
        "last_3_months": "近三个月",
        "last_6_months": "近六个月",
    }
    return mapping.get(dimension, dimension)
