"""
工作手机SDK v3.0 - 存客宝对接路由
CunKeBao API Router

路由前缀：/api/v3/cunke-bao
功能：
  - 配置管理（设置/查询 API Key 等）
  - 手动触发线索上报
  - Frida Hook 事件接收与转发
  - 服务状态查询

作者：Manus AI
版本：v1.0.0
日期：2026-05-15
"""

from fastapi import APIRouter, HTTPException, BackgroundTasks
from pydantic import BaseModel, Field
from typing import Optional, List, Dict, Any
import logging
import time

from services.cunke_bao_service import (
    cunke_bao_service,
    CunKeBaoConfig,
    LeadData,
    FriendAddEvent,
    GroupChangeEvent,
)

router = APIRouter()
logger = logging.getLogger(__name__)


# ═══════════════════════════════════════════════
# 一、请求/响应模型
# ═══════════════════════════════════════════════

class CKBConfigRequest(BaseModel):
    """存客宝配置请求"""
    api_key: str = Field(..., description="存客宝 API Key")
    base_url: str = Field(
        "https://ckbapi.quwanzhi.com/v1/api/scenarios",
        description="存客宝接口地址"
    )
    timeout: int = Field(10, ge=1, le=60, description="请求超时秒数")
    max_retries: int = Field(3, ge=1, le=10, description="最大重试次数")
    rate_limit_per_minute: int = Field(60, ge=1, le=600, description="每分钟最大请求数")
    enabled: bool = Field(True, description="是否启用")


class LeadReportRequest(BaseModel):
    """线索上报请求"""
    phone: str = Field("", description="手机号")
    name: str = Field("", description="姓名")
    source: str = Field("微信", description="来源渠道")
    wechat_id: str = Field("", description="微信号")
    wechat_nickname: str = Field("", description="微信昵称")
    wechat_remark: str = Field("", description="备注名")
    tags: List[str] = Field(default_factory=list, description="标签列表")
    group_name: str = Field("", description="所在群名")
    device_id: str = Field("", description="设备ID")
    extra: Dict[str, Any] = Field(default_factory=dict, description="扩展字段")


class FriendAddEventRequest(BaseModel):
    """新好友添加事件请求（来自 Frida Hook）"""
    device_id: str = Field(..., description="设备ID")
    wechat_id: str = Field(..., description="微信号")
    nickname: str = Field("", description="昵称")
    avatar: str = Field("", description="头像URL")
    source: str = Field("微信添加", description="来源")


class GroupChangeEventRequest(BaseModel):
    """群变动事件请求（来自 Frida Hook）"""
    device_id: str = Field(..., description="设备ID")
    group_id: str = Field(..., description="群ID")
    group_name: str = Field("", description="群名称")
    event_type: str = Field(..., description="事件类型: member_join/member_leave/group_create")
    member_wechat_id: str = Field("", description="成员微信号")
    member_nickname: str = Field("", description="成员昵称")


class BatchContactRequest(BaseModel):
    """批量联系人上报请求"""
    device_id: str = Field(..., description="设备ID")
    source: str = Field("微信通讯录", description="来源")
    contacts: List[Dict[str, Any]] = Field(..., description="联系人列表")


# ═══════════════════════════════════════════════
# 二、配置管理接口
# ═══════════════════════════════════════════════

@router.post("/cunke-bao/config", tags=["存客宝对接"])
async def set_config(req: CKBConfigRequest):
    """
    设置存客宝对接配置

    配置 API Key、接口地址、超时等参数，并启用/禁用服务。
    """
    config = CunKeBaoConfig(
        api_key=req.api_key,
        base_url=req.base_url,
        timeout=req.timeout,
        max_retries=req.max_retries,
        rate_limit_per_minute=req.rate_limit_per_minute,
        enabled=req.enabled,
    )
    cunke_bao_service.update_config(config)
    return {
        "code": 200,
        "msg": "配置已更新",
        "data": {
            "enabled": config.enabled,
            "base_url": config.base_url,
            "api_key": "***" + config.api_key[-4:] if len(config.api_key) > 4 else "***",
        }
    }


@router.get("/cunke-bao/config", tags=["存客宝对接"])
async def get_config():
    """查询当前存客宝配置（API Key 脱敏显示）"""
    cfg = cunke_bao_service.config
    return {
        "code": 200,
        "data": {
            "enabled": cfg.enabled,
            "base_url": cfg.base_url,
            "api_key_set": bool(cfg.api_key),
            "api_key_preview": ("***" + cfg.api_key[-4:]) if len(cfg.api_key) > 4 else ("***" if cfg.api_key else ""),
            "timeout": cfg.timeout,
            "max_retries": cfg.max_retries,
            "rate_limit_per_minute": cfg.rate_limit_per_minute,
        }
    }


@router.get("/cunke-bao/stats", tags=["存客宝对接"])
async def get_stats():
    """查询存客宝服务统计信息"""
    return {
        "code": 200,
        "data": cunke_bao_service.get_stats()
    }


# ═══════════════════════════════════════════════
# 三、线索上报接口
# ═══════════════════════════════════════════════

@router.post("/cunke-bao/report-lead", tags=["存客宝对接"])
async def report_lead(req: LeadReportRequest):
    """
    手动上报线索到存客宝

    可用于测试或特殊场景下的手动触发。
    """
    lead = LeadData(
        phone=req.phone,
        name=req.name,
        source=req.source,
        wechat_id=req.wechat_id,
        wechat_nickname=req.wechat_nickname,
        wechat_remark=req.wechat_remark,
        tags=req.tags,
        group_name=req.group_name,
        device_id=req.device_id,
        extra=req.extra,
    )
    result = await cunke_bao_service.report_lead(lead)
    return result


@router.post("/cunke-bao/batch-contacts", tags=["存客宝对接"])
async def batch_report_contacts(req: BatchContactRequest, background_tasks: BackgroundTasks):
    """
    批量上报联系人到存客宝

    通常由 Frida Hook 获取通讯录后调用，支持后台异步处理。
    """
    if not req.contacts:
        raise HTTPException(400, "contacts 列表不能为空")

    if len(req.contacts) > 500:
        raise HTTPException(400, "单次批量上报最多 500 条")

    # 超过 10 条时异步处理，避免请求超时
    if len(req.contacts) > 10:
        background_tasks.add_task(
            cunke_bao_service.batch_report_contacts,
            req.contacts,
            req.device_id,
            req.source,
        )
        return {
            "code": 200,
            "msg": f"已接收 {len(req.contacts)} 条联系人，正在后台处理",
            "data": {"total": len(req.contacts), "async": True}
        }
    else:
        result = await cunke_bao_service.batch_report_contacts(
            req.contacts, req.device_id, req.source
        )
        return {"code": 200, "msg": "批量上报完成", "data": result}


# ═══════════════════════════════════════════════
# 四、Frida Hook 事件接收接口
# ═══════════════════════════════════════════════

@router.post("/cunke-bao/hook/friend-add", tags=["存客宝对接", "Frida Hook"])
async def hook_friend_add(req: FriendAddEventRequest):
    """
    接收 Frida Hook 上报的新好友添加事件

    设备端 Agent 在检测到新好友添加时调用此接口，
    服务端将自动转换为存客宝线索并上报。
    """
    event = FriendAddEvent(
        device_id=req.device_id,
        wechat_id=req.wechat_id,
        nickname=req.nickname,
        avatar=req.avatar,
        source=req.source,
    )
    logger.info(f"[CKB] 收到新好友事件: device={req.device_id}, wechat_id={req.wechat_id}")
    result = await cunke_bao_service.report_friend_add(event)
    return result


@router.post("/cunke-bao/hook/group-change", tags=["存客宝对接", "Frida Hook"])
async def hook_group_change(req: GroupChangeEventRequest):
    """
    接收 Frida Hook 上报的群变动事件

    设备端 Agent 在检测到群成员变动时调用此接口，
    服务端将自动处理并按需上报到存客宝。
    """
    event = GroupChangeEvent(
        device_id=req.device_id,
        group_id=req.group_id,
        group_name=req.group_name,
        event_type=req.event_type,
        member_wechat_id=req.member_wechat_id,
        member_nickname=req.member_nickname,
    )
    logger.info(f"[CKB] 收到群变动事件: type={req.event_type}, group={req.group_name}")
    result = await cunke_bao_service.report_group_change(event)
    return result


@router.post("/cunke-bao/hook/batch-events", tags=["存客宝对接", "Frida Hook"])
async def hook_batch_events(
    events: List[Dict[str, Any]],
    background_tasks: BackgroundTasks
):
    """
    批量接收 Frida Hook 事件

    设备端可将多个事件打包一次性上报，减少网络请求次数。
    支持的事件类型：friend_add / group_change / contact_update
    """
    if not events:
        raise HTTPException(400, "events 列表不能为空")

    async def process_events():
        for evt in events:
            evt_type = evt.get("type", "")
            try:
                if evt_type == "friend_add":
                    event = FriendAddEvent(
                        device_id=evt.get("device_id", ""),
                        wechat_id=evt.get("wechat_id", ""),
                        nickname=evt.get("nickname", ""),
                        avatar=evt.get("avatar", ""),
                        source=evt.get("source", "微信添加"),
                    )
                    await cunke_bao_service.report_friend_add(event)
                elif evt_type == "group_change":
                    event = GroupChangeEvent(
                        device_id=evt.get("device_id", ""),
                        group_id=evt.get("group_id", ""),
                        group_name=evt.get("group_name", ""),
                        event_type=evt.get("event_type", ""),
                        member_wechat_id=evt.get("member_wechat_id", ""),
                        member_nickname=evt.get("member_nickname", ""),
                    )
                    await cunke_bao_service.report_group_change(event)
                elif evt_type == "contact_update":
                    contacts = evt.get("contacts", [])
                    device_id = evt.get("device_id", "")
                    if contacts and device_id:
                        await cunke_bao_service.batch_report_contacts(
                            contacts, device_id, "微信通讯录更新"
                        )
            except Exception as e:
                logger.error(f"[CKB] 处理事件失败 type={evt_type}: {e}")

    background_tasks.add_task(process_events)
    return {
        "code": 200,
        "msg": f"已接收 {len(events)} 个事件，正在后台处理",
        "data": {"total": len(events)}
    }
