"""应用 6 备注分析 Prompt 拼装。

助教提交备注后触发，AI 分析备注内容并评分（1-10）+ 提取维客线索。
- 数据源：context.note_content + fetch_member_consumption_data + fetch_member_notes
- 线索 category：6 选 1（含促销偏好/社交关系/重要反馈）
- 线索 providers 标记当前备注提供人
- system prompt 在百炼控制台配置

返回：单个 prompt 字符串。
"""

from __future__ import annotations

import asyncio
import json
import logging
from typing import Any

from app.ai.cache_service import AICacheService
from app.ai.data_fetchers import fetch_member_consumption_data, fetch_member_notes
from app.ai.schemas import CacheTypeEnum
from app.services.runtime_context import as_runtime_business_now_str

logger = logging.getLogger(__name__)

_MAX_PROMPT_LEN = 8000


async def build_prompt(
    context: dict,
    cache_svc: AICacheService | None = None,
) -> str:
    """构建 App6 prompt 字符串。

    Args:
        context: site_id, member_id, note_content, noted_by_name, noted_by_created_at

    Returns:
        JSON 序列化后的 prompt 字符串
    """
    site_id = context["site_id"]
    member_id = context["member_id"]
    note_content = context.get("note_content", "")
    noted_by_name = context.get("noted_by_name", "")
    noted_by_created_at = context.get("noted_by_created_at", "")

    results = await asyncio.gather(
        fetch_member_consumption_data(site_id, member_id),
        fetch_member_notes(site_id, member_id),
        return_exceptions=True,
    )

    warnings: list[str] = []

    if isinstance(results[0], Exception):
        member_data = _default_member_data()
        warnings.append("消费数据获取失败")
        logger.warning("App6 消费数据获取失败: %s", results[0])
    else:
        member_data = results[0]

    all_notes = results[1] if not isinstance(results[1], Exception) else []
    if isinstance(results[1], Exception):
        warnings.append("备注获取失败")
        logger.warning("App6 备注获取失败: %s", results[1])

    reference = _build_reference(site_id, member_id, cache_svc)
    reference["member_nickname"] = member_data.get("member_nickname", "")
    reference["consumption_data"] = {
        "consumption_records": member_data.get("consumption_records", []) or "该客户暂无消费记录",
        "member_cards": member_data.get("member_cards", []),
        "card_balance_total": member_data.get("card_balance_total", 0),
        "stored_value_balance_total": member_data.get("stored_value_balance_total", 0),
        "expected_visit_date": member_data.get("expected_visit_date"),
        "days_since_last_visit": member_data.get("days_since_last_visit"),
    }
    reference["all_notes"] = all_notes

    payload: dict[str, Any] = {
        "current_time": as_runtime_business_now_str(site_id, fmt="%Y-%m-%d %H:%M"),
        "member_id": member_id,
        "current_note": {
            "content": note_content,
            "recorded_by": noted_by_name,
            "created_at": noted_by_created_at,
        },
        "providers_label": noted_by_name,
        "reference": reference,
    }

    if warnings:
        payload["_data_warnings"] = warnings

    return _truncate_payload(payload)


def _default_member_data() -> dict:
    return {
        "member_nickname": "",
        "consumption_records": [],
        "member_cards": [],
        "card_balance_total": 0,
        "stored_value_balance_total": 0,
        "expected_visit_date": None,
        "days_since_last_visit": None,
    }


def _build_reference(
    site_id: int,
    member_id: int,
    cache_svc: AICacheService | None,
) -> dict:
    """组装 App3 客户线索最新 + App8 历史最近 2 条。"""
    if cache_svc is None:
        return {}

    ref: dict = {}
    target_id = str(member_id)

    app3_latest = cache_svc.get_latest(
        CacheTypeEnum.APP3_CLUE.value, site_id, target_id,
    )
    if app3_latest:
        ref["app3_clues"] = {
            "result_json": app3_latest.get("result_json"),
            "generated_at": app3_latest.get("created_at"),
        }

    app8_history = cache_svc.get_history(
        CacheTypeEnum.APP8_CLUE_CONSOLIDATED.value, site_id, target_id, limit=2,
    )
    if app8_history:
        ref["app8_history"] = [
            {"result_json": h.get("result_json"), "generated_at": h.get("created_at")}
            for h in app8_history
        ]

    return ref


def _truncate_payload(payload: dict) -> str:
    """按优先级截断 consumption_records → all_notes。"""
    text = json.dumps(payload, ensure_ascii=False, default=str)
    if len(text) <= _MAX_PROMPT_LEN:
        return text

    cd = payload["reference"].get("consumption_data", {})
    records = cd.get("consumption_records")
    if isinstance(records, list) and len(records) > 5:
        cd["consumption_records"] = records[:5]
        cd["_truncated"] = f"消费记录已截断，原始 {len(records)} 条"
        text = json.dumps(payload, ensure_ascii=False, default=str)
    if len(text) > _MAX_PROMPT_LEN:
        notes = payload["reference"].get("all_notes")
        if isinstance(notes, list) and len(notes) > 10:
            payload["reference"]["all_notes"] = notes[:10]
            payload["reference"]["_truncated_notes"] = f"备注已截断，原始 {len(notes)} 条"
            text = json.dumps(payload, ensure_ascii=False, default=str)
    return text
