#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
AI 视图共用辅助：请求体解析、AI 客户端创建、SSE 格式化。
供 ai_chat、ai_ppt、ai_docx、ai_excel 等通过 ViewSet 注入的 _parse_body、_get_client、_sse_event 使用。
"""

import json
import logging
from typing import Any

from django.conf import settings
from rest_framework.request import Request

from django_base_ai.utils.ai import get_client, get_client_from_settings

logger = logging.getLogger(__name__)


class AIViewsHelper:
    """ai_chat / ai_ppt / ai_docx / ai_excel 共用：解析 body、创建客户端、SSE 格式。"""

    @staticmethod
    def parse_body(request: Request) -> dict[str, Any]:
        """
        解析 POST 请求体为 dict，无效或非 dict 返回空 dict。
        兼容：application/json 的 dict、raw 字符串、multipart 时的 QueryDict（排除 FILES 键）。
        """
        data = getattr(request, "data", None)
        if data is None:
            return {}
        if isinstance(data, str):
            try:
                return json.loads(data) if data.strip() else {}
            except json.JSONDecodeError:
                return {}
        if isinstance(data, dict):
            return data
        if hasattr(data, "keys") and not isinstance(data, dict):
            return {k: data.get(k) for k in data.keys() if k not in getattr(request, "FILES", {})}
        return {}

    @staticmethod
    def get_client(body: dict[str, Any]) -> tuple[Any, str | None]:
        """
        根据 body 创建 AI 客户端。返回 (client, error_msg)，成功时 error_msg 为 None。
        use_settings=True 时从 conf 读 api_key/base_url；False 时需 body 传 api_key。
        不传 provider 时使用配置 AI_DEFAULT_PROVIDER，默认 deepseek。
        """
        use_settings = body.get("use_settings", True)
        provider = (
            (body.get("provider") or getattr(settings, "AI_DEFAULT_PROVIDER", None) or "deepseek")
            .strip()
            or "deepseek"
        )
        model = body.get("model")
        if use_settings:
            try:
                return get_client_from_settings(provider), None
            except ValueError as e:
                return None, str(e)
            except Exception as e:
                logger.exception("AI client init failed")
                return None, f"初始化 AI 客户端失败: {e}"
        api_key = (body.get("api_key") or "").strip()
        if not api_key:
            return None, "use_settings 为 false 时需传 api_key"
        base_url = body.get("base_url") or None
        try:
            client = get_client(
                provider, api_key=api_key, base_url=base_url, default_model=model
            )
            return client, None
        except ValueError as e:
            return None, str(e)
        except Exception as e:
            logger.exception("AI client init failed")
            return None, f"初始化 AI 客户端失败: {e}"

    @staticmethod
    def sse_data(obj: dict[str, Any]) -> str:
        """格式化为 SSE 单条：data: {json}\\n\\n，ensure_ascii=False 保证中文不转 \\uXXXX。"""
        return f"data: {json.dumps(obj, ensure_ascii=False)}\n\n"

    @staticmethod
    def sse_event(event_name: str, data: dict[str, Any]) -> str:
        """格式化为带 event 类型的 SSE：event: xxx\\ndata: {json}\\n\\n。"""
        return f"event: {event_name}\ndata: {json.dumps(data, ensure_ascii=False)}\n\n"
