"""
CRM 客户模块路由 —— /api/customers
薄路由层：参数解析 + 调用 Service + 包装响应
"""
from __future__ import annotations
import uuid
from fastapi import APIRouter, Depends, Query, Request
from sqlalchemy.ext.asyncio import AsyncSession
from app.api.deps import get_current_user
from app.db.database import get_db
from app.schemas.auth import CurrentUserPayload
from app.schemas.crm import CustomerCreate, CustomerUpdate
from app.schemas.response import ok
from app.services import customer_service as svc

router = APIRouter(prefix="/customers", tags=["客户管理"])


@router.post("", summary="新增客户")
async def create_customer(
    body: CustomerCreate,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    result = await svc.create_customer(db, current_user, body)
    return ok(data=result.model_dump(mode="json"), message="客户创建成功")


@router.get("", summary="分页获取客户列表（含数据权限隔离）")
async def list_customers(
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(20, ge=1, le=100, description="每页数量"),
    keyword: str | None = Query(None, description="名称模糊搜索"),
    level: str | None = Query(None, pattern=r"^[ABC]$", description="客户等级"),
    include_archived: bool = Query(False, description="是否包含已归档客户"),
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    result = await svc.list_customers(db, current_user, page, size, keyword, level, include_archived)
    return ok(data=result.model_dump(mode="json"))


@router.get("/search", summary="模糊搜索客户（远程选择器用）")
async def search_customers(
    q: str = Query(..., min_length=1, max_length=100, description="搜索关键词"),
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    result = await svc.search_customers(db, current_user, q)
    return ok(data=result)


@router.get("/{customer_id}", summary="获取客户详情")
async def get_customer(
    customer_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    result = await svc.get_customer(db, current_user, customer_id)
    return ok(data=result.model_dump(mode="json"))


@router.put("/{customer_id}", summary="修改客户信息")
async def update_customer(
    customer_id: uuid.UUID,
    body: CustomerUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    result = await svc.update_customer(db, current_user, customer_id, body)
    return ok(data=result.model_dump(mode="json"), message="客户信息已更新")


@router.delete("/{customer_id}", summary="软删除客户")
async def delete_customer(
    customer_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    await svc.delete_customer(db, current_user, customer_id)
    return ok(message="客户已归档")


@router.put("/{customer_id}/restore", summary="恢复已归档客户")
async def restore_customer(
    customer_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    await svc.restore_customer(db, current_user, customer_id)
    return ok(message="客户已恢复")


@router.get("/{customer_id}/products", summary="获取客户关联产品（通过订单反查）")
async def get_customer_products(
    customer_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    result = await svc.get_customer_products(db, current_user, customer_id)
    return ok(data=result)


@router.put("/{customer_id}/persona", summary="双轨画像回写（Dify Workflow 回调）")
async def update_customer_persona(
    customer_id: uuid.UUID,
    request: Request,
    db: AsyncSession = Depends(get_db),
) -> dict:
    """
    V5.0 双轨画像回写 — 容错解析 Dify Workflow 回调 body。
    支持以下格式：
    1. 标准 JSON: {"company_updates": {...}, "contact_updates": [...]}
    2. Dify 空 key 包装: {"": "JSON字符串"}
    3. Qwen3.5 CoT 包裹: <think>...</think> + JSON
    """
    import json as _json
    import re

    raw = await request.body()
    raw_str = raw.decode("utf-8", errors="replace").strip()

    # ── 统一预处理：去除 <think>...</think> 标签 ──
    cleaned = re.sub(r'<think>[\s\S]*?</think>', '', raw_str, flags=re.DOTALL).strip()
    # 也处理可能缺少闭合的 <think>
    cleaned = re.sub(r'<think>[\s\S]*$', '', cleaned, flags=re.DOTALL).strip()

    body = None

    # 策略1：清理后直接 JSON 解析
    try:
        parsed = _json.loads(cleaned)
        if isinstance(parsed, dict):
            body = parsed
        elif isinstance(parsed, list):
            # 从数组中找到含画像 key 的 dict
            for item in parsed:
                if isinstance(item, dict) and len(item) > 1:
                    body = item
                    break
    except _json.JSONDecodeError:
        pass

    # 策略2：Dify 空 key 包装 {"": "...JSON..."}
    if not body:
        try:
            wrapped = _json.loads(raw_str)
            if isinstance(wrapped, dict):
                values = list(wrapped.values())
                if len(values) == 1 and isinstance(values[0], str):
                    inner = re.sub(r'<think>[\s\S]*?</think>', '', values[0], flags=re.DOTALL).strip()
                    try:
                        body = _json.loads(inner)
                    except _json.JSONDecodeError:
                        pass
        except _json.JSONDecodeError:
            pass

    # 策略3：正则从文本中提取最外层 JSON 对象 {...}
    if not body or not isinstance(body, dict):
        # 找到第一个 { 到最后一个 } 之间的内容
        m = re.search(r'\{', cleaned)
        if m:
            start = m.start()
            # 用计数法匹配完整的 JSON 对象
            depth = 0
            end = start
            for i in range(start, len(cleaned)):
                if cleaned[i] == '{': depth += 1
                elif cleaned[i] == '}': depth -= 1
                if depth == 0:
                    end = i + 1
                    break
            if depth == 0:
                try:
                    body = _json.loads(cleaned[start:end])
                except _json.JSONDecodeError:
                    pass

    if not body or not isinstance(body, dict):
        print(f"[Persona] 无法解析 body ({len(raw_str)} chars): {cleaned[:300]}")
        return ok(message="画像回写失败：无法解析请求体")

    print(f"[Persona] 解析成功，keys={list(body.keys())}")

    from app.models.crm import CrmCustomer, CrmContact
    from sqlalchemy import update as sa_update

    # Key 模糊映射：LLM 可能不严格遵循 key name
    _COMPANY_KEYS = {"company_updates", "company_info", "firmographics", "company", "企业画像"}
    _CONTACT_KEYS = {"contact_updates", "contacts", "contact_info", "buyer_updates", "联系人画像"}

    company_updates = None
    contact_updates = None
    for k, v in body.items():
        kl = k.lower().strip()
        print(f"[Persona]   key='{k}' type={type(v).__name__}")
        if kl in _COMPANY_KEYS or "company" in kl or "firm" in kl:
            if isinstance(v, dict):
                company_updates = v
            elif isinstance(v, str):
                try:
                    company_updates = _json.loads(v)
                except _json.JSONDecodeError:
                    company_updates = {"summary": v}
        elif kl in _CONTACT_KEYS or "contact" in kl:
            if isinstance(v, list):
                contact_updates = v
            elif isinstance(v, dict):
                contact_updates = [v]
            elif isinstance(v, str):
                try:
                    parsed_contacts = _json.loads(v)
                    contact_updates = parsed_contacts if isinstance(parsed_contacts, list) else [parsed_contacts]
                except _json.JSONDecodeError:
                    pass

    # 如果 company_updates 没有标准结构但有 firmographics/dynamic_status 在顶层
    if not company_updates and ("firmographics" in body or "dynamic_status" in body):
        company_updates = {
            "firmographics": body.get("firmographics", {}),
            "dynamic_status": body.get("dynamic_status", {}),
        }

    # 如果完全没匹配到 company key，但 body 本身看起来就是画像数据，直接用整个 body
    if not company_updates and not contact_updates:
        company_updates = body

    print(f"[Persona] company={'有' if company_updates else '无'}, contacts={len(contact_updates) if contact_updates else 0}条")

    # ── 企业级画像合并 ──
    if company_updates:
        customer = await db.get(CrmCustomer, customer_id)
        if customer:
            merged = _deep_merge(customer.ai_persona or {}, company_updates)
            stmt = (
                sa_update(CrmCustomer)
                .where(CrmCustomer.id == customer_id)
                .values(ai_persona=merged)
            )
            await db.execute(stmt)

    # ── 联系人级画像合并 ──
    if contact_updates and isinstance(contact_updates, list):
        for cu in contact_updates:
            cid = cu.get("contact_id")
            if not cid:
                continue
            try:
                contact = await db.get(CrmContact, uuid.UUID(cid))
            except (ValueError, TypeError):
                continue
            if not contact:
                continue
            updates = {k: v for k, v in cu.items() if k != "contact_id" and v is not None}
            merged = _deep_merge(contact.ai_buyer_persona or {}, updates)
            contact.ai_buyer_persona = merged

    await db.commit()
    return ok(message="画像更新成功")


def _deep_merge(base: dict, override: dict) -> dict:
    """递归深度合并两个 dict（增量模式）。
    规则：
    - dict + dict → 递归合并
    - list + list → 追加去重
    - 新值为空（空字符串/空列表/空dict/None）→ 保留旧值
    - 新值非空 → 覆盖旧值
    """
    result = base.copy()
    for k, v in override.items():
        old = result.get(k)
        # 空值不覆盖已有数据
        if old and (v is None or v == "" or v == [] or v == {}):
            continue
        if isinstance(old, dict) and isinstance(v, dict):
            result[k] = _deep_merge(old, v)
        elif isinstance(old, list) and isinstance(v, list):
            # 列表去重追加
            seen = set(str(x) for x in old)
            result[k] = old + [x for x in v if str(x) not in seen]
        else:
            result[k] = v
    return result

