#!/usr/bin/env python3
"""Build Feishu/DingTalk writeback payloads from inquiry scoring results.

The script does not call external CLIs by itself. It prepares table rows,
internal notification messages, and explicit command plans for Accio Work to
execute after customer authorization is confirmed.
"""

from __future__ import annotations

import argparse
import json
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional


DEFAULT_CONFIG: Dict[str, Any] = {
    "customer_name": "",
    "table_name": "新询盘分级跟进表",
    "enabled_platforms": ["feishu", "dingtalk"],
    "notify_grades": ["S", "A"],
    "notify_scope": "internal_only",
    "feishu": {
        "enabled": True,
        "cli_name": "feishu",
        "base_id": "",
        "table_id": "",
        "owner_chat_id": "",
    },
    "dingtalk": {
        "enabled": True,
        "cli_name": "dingtalk",
        "table_id": "",
        "robot_webhook": "",
        "owner_chat_id": "",
    },
}


def read_json(path: Path) -> Any:
    return json.loads(path.read_text(encoding="utf-8"))


def deep_merge(base: Dict[str, Any], override: Optional[Dict[str, Any]]) -> Dict[str, Any]:
    merged = json.loads(json.dumps(base, ensure_ascii=False))
    if not isinstance(override, dict):
        return merged
    for key, value in override.items():
        if isinstance(value, dict) and isinstance(merged.get(key), dict):
            merged[key].update(value)
        else:
            merged[key] = value
    return merged


def load_results(payload: Any) -> List[Dict[str, Any]]:
    if isinstance(payload, dict) and isinstance(payload.get("results"), list):
        return payload["results"]
    if isinstance(payload, list):
        return payload
    raise ValueError("input must be score_inquiry_v3.py JSON output or a result list")


def table_row(item: Dict[str, Any]) -> Dict[str, Any]:
    return {
        "inquiry_id": item.get("inquiry_id"),
        "received_at": item.get("received_at"),
        "updated_at": item.get("updated_at"),
        "source": item.get("source"),
        "buyer_name": item.get("buyer_name"),
        "buyer_country": item.get("buyer_country"),
        "product": item.get("product"),
        "score": item.get("score"),
        "grade": item.get("grade"),
        "assignee": item.get("assignee") or "",
        "next_action": item.get("next_action"),
        "missing_fields": ", ".join(item.get("missing_fields") or []),
        "human_confirmation_items": "；".join(item.get("human_confirmation_items") or []),
        "followup_questions": "；".join(item.get("followup_questions") or []),
        "confirmation_status": "待确认",
        "owner_note": "",
    }


def message_card(item: Dict[str, Any], customer_name: str = "") -> Dict[str, Any]:
    title_prefix = f"{customer_name} " if customer_name else ""
    grade = item.get("grade")
    return {
        "title": f"{title_prefix}新询盘{grade}类提醒：{item.get('buyer_name') or item.get('inquiry_id')}",
        "summary": f"{item.get('grade')}类｜{item.get('score')}分｜{item.get('buyer_country') or '国家缺失'}｜{item.get('product') or '产品缺失'}",
        "body": [
            f"询盘 ID：{item.get('inquiry_id')}",
            f"买家：{item.get('buyer_name') or '未知'}",
            f"产品：{item.get('product') or '缺失'}",
            f"下一步：{item.get('next_action')}",
            "人工确认：" + "；".join(item.get("human_confirmation_items") or []),
        ],
        "notify_scope": "internal_only",
    }


def command_plan(config: Dict[str, Any], row_count: int, message_count: int) -> List[Dict[str, Any]]:
    plan: List[Dict[str, Any]] = []
    feishu = config.get("feishu") or {}
    dingtalk = config.get("dingtalk") or {}
    if feishu.get("enabled"):
        plan.append({
            "platform": "feishu",
            "purpose": "create_or_update_customer_inquiry_table",
            "cli": feishu.get("cli_name") or "feishu",
            "requires": ["Feishu app authorization", "base_id/table_id or permission to create table"],
            "payload_key": "feishu.table_rows",
            "row_count": row_count,
            "execute_after_authorization": True,
        })
        if message_count:
            plan.append({
                "platform": "feishu",
                "purpose": "send_internal_high_priority_message",
                "cli": feishu.get("cli_name") or "feishu",
                "requires": ["owner_chat_id or approved group/channel"],
                "payload_key": "feishu.messages",
                "message_count": message_count,
                "execute_after_authorization": True,
            })
    if dingtalk.get("enabled"):
        plan.append({
            "platform": "dingtalk",
            "purpose": "create_or_update_customer_inquiry_table",
            "cli": dingtalk.get("cli_name") or "dingtalk",
            "requires": ["DingTalk CLI authorization", "AI table/app/table permission"],
            "payload_key": "dingtalk.table_rows",
            "row_count": row_count,
            "execute_after_authorization": True,
        })
        if message_count:
            plan.append({
                "platform": "dingtalk",
                "purpose": "send_internal_high_priority_message",
                "cli": dingtalk.get("cli_name") or "dingtalk",
                "requires": ["robot_webhook or approved chat_id"],
                "payload_key": "dingtalk.messages",
                "message_count": message_count,
                "execute_after_authorization": True,
            })
    return plan


def build_payload(score_payload: Any, config: Dict[str, Any]) -> Dict[str, Any]:
    results = load_results(score_payload)
    notify_grades = set(config.get("notify_grades") or ["S", "A"])
    rows = [table_row(item) for item in results]
    messages = [message_card(item, config.get("customer_name") or "") for item in results if item.get("grade") in notify_grades]
    return {
        "schema_version": "0.1",
        "generated_at": datetime.now().isoformat(timespec="seconds"),
        "status": "preview_payload",
        "authorization_required": True,
        "safety_note": "Only internal table writeback and internal notifications are prepared. No buyer-facing message should be sent by this payload.",
        "table_name": config.get("table_name"),
        "summary": {
            "row_count": len(rows),
            "message_count": len(messages),
            "notify_grades": sorted(notify_grades),
        },
        "feishu": {
            "table_rows": rows,
            "messages": messages,
        },
        "dingtalk": {
            "table_rows": rows,
            "messages": messages,
        },
        "command_plan": command_plan(config, len(rows), len(messages)),
    }


def main() -> None:
    parser = argparse.ArgumentParser(description="Build Feishu/DingTalk writeback payloads from score results")
    parser.add_argument("score_json", help="score_inquiry_v3.py --json output")
    parser.add_argument("--config", help="platform writeback config JSON")
    parser.add_argument("--output", "-o", help="output payload JSON; stdout if omitted")
    args = parser.parse_args()

    score_payload = read_json(Path(args.score_json))
    config = DEFAULT_CONFIG
    if args.config:
        config = deep_merge(DEFAULT_CONFIG, read_json(Path(args.config)))
    payload = build_payload(score_payload, config)
    text = json.dumps(payload, ensure_ascii=False, indent=2)
    if args.output:
        path = Path(args.output)
        path.parent.mkdir(parents=True, exist_ok=True)
        path.write_text(text + "\n", encoding="utf-8")
    else:
        print(text)


if __name__ == "__main__":
    main()
