"""TrailBase 客户端主类 - 使用官方 SDK"""

import base64
import json
import os
from typing import Any

import httpx
from trailbase import Client, Tokens


class TrailBaseClient:
    """TrailBase API 客户端 - 使用官方 SDK"""

    def __init__(
        self,
        base_url: str | None = None,
        token: str | None = None,
        timeout: float = 10.0,
        read_timeout: float = 30.0,
    ):
        """
        初始化客户端

        Args:
            base_url: TrailBase 服务器地址，默认从 TRAILBASE_URL 环境变量读取
            token: 认证令牌，默认从 ADMIN_TOKEN 环境变量读取
            timeout: 连接超时（秒）
            read_timeout: 读取超时（秒）
        """
        self.base_url = base_url or os.getenv("TRAILBASE_URL", "")
        if not self.base_url:
            raise ValueError("base_url is required or set TRAILBASE_URL environment variable")

        self.token = token or os.getenv("ADMIN_TOKEN")
        
        # 从 JWT 中提取 CSRF token
        csrf_token = self._extract_csrf_token(self.token) if self.token else None
        
        # 创建 Tokens 对象（refresh_token 可以为 None）
        tokens = Tokens(self.token, None, csrf_token) if self.token else None
        
        # 创建 HTTP 客户端
        http_client = httpx.Client(
            timeout=httpx.Timeout(timeout, read=read_timeout),
            follow_redirects=True,
        )
        
        # 使用 SDK 的 Client
        self._sdk_client = Client(self.base_url, tokens=tokens, http_client=http_client)

    def _extract_csrf_token(self, token: str) -> str | None:
        """从 JWT token 中提取 CSRF token"""
        try:
            parts = token.split(".")
            if len(parts) >= 2:
                payload = parts[1]
                padding = 4 - len(payload) % 4
                if padding != 4:
                    payload += "=" * padding
                decoded = base64.urlsafe_b64decode(payload)
                payload_data = json.loads(decoded)
                return payload_data.get("csrf_token")
        except Exception:
            pass
        return None

    def close(self) -> None:
        """关闭客户端"""
        # SDK 客户端会自动清理
        pass

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()
    
    @property
    def http(self):
        """HTTP 客户端（兼容性属性）"""
        return SDKHTTPWrapper(self._sdk_client)


class SDKHTTPWrapper:
    """SDK Client 的 HTTP 包装器，提供统一的 HTTP 接口"""
    
    def __init__(self, sdk_client: Client):
        self.sdk_client = sdk_client
    
    def _normalize_params(self, params: dict[str, Any] | None) -> dict[str, str] | None:
        """将参数转换为 SDK 需要的格式（所有值转为字符串）
        
        对于复杂类型（dict/list），使用 json.dumps 序列化为 JSON 字符串
        对于简单类型，直接转为字符串
        """
        if params is None:
            return None
        normalized = {}
        for k, v in params.items():
            if isinstance(v, (dict, list)):
                # 复杂参数使用 JSON 序列化
                normalized[k] = json.dumps(v, ensure_ascii=False)
            else:
                # 简单参数直接转为字符串
                normalized[k] = str(v)
        return normalized
    
    def _format_error(self, code: str, message: str, details: dict[str, Any] | None = None) -> dict[str, Any]:
        """统一格式化错误响应
        
        Returns:
            标准化的错误字典: {"error": {"code": "...", "message": "...", "details": ...}}
        """
        error_obj: dict[str, Any] = {
            "code": code,
            "message": message,
        }
        if details:
            error_obj["details"] = details
        return {"error": error_obj}
    
    def _handle_response(self, response: httpx.Response) -> dict[str, Any]:
        """处理响应，包括错误处理"""
        # 检查 HTTP 状态码
        if response.status_code >= 400:
            error_data = {}
            raw_text = None
            try:
                error_data = response.json()
            except Exception:
                # JSON 解析失败，尝试获取原始文本
                try:
                    raw_text = response.text
                except Exception:
                    raw_text = str(response.content[:500])
            
            code = error_data.get("code", f"HTTP_{response.status_code}")
            message = error_data.get("message", raw_text or response.text or response.reason_phrase)
            details = error_data.get("details", {})
            
            # 如果 error_data 中有其他字段，也添加到 details 中
            if error_data and not details:
                details = {k: v for k, v in error_data.items() if k not in ("code", "message", "details")}
            if raw_text and not details:
                details = {"raw_response": raw_text}
            
            from trailbase_mcp.client.errors import TrailBaseHTTPError
            raise TrailBaseHTTPError(
                status_code=response.status_code,
                code=code,
                message=message,
                details=details,
            )
        
        if response.status_code == 204:
            return {}
        
        # 检查内容类型
        content_type = response.headers.get("content-type", "").lower()
        if not response.content:
            return {}
        
        # 尝试解析 JSON（SDK 应该已经处理了 protobuf）
        if "application/json" in content_type or "json" in content_type:
            try:
                return response.json()
            except Exception as e:
                # JSON 解析失败，返回原始响应信息
                return {
                    "error": f"Failed to parse JSON: {str(e)}",
                    "content_type": content_type,
                    "content_length": len(response.content),
                    "raw_content_preview": response.content[:100].hex() if len(response.content) > 0 else None,
                }
        else:
            # 非 JSON 响应，返回原始内容
            # SDK 应该已经处理了 protobuf 等格式
            try:
                # 尝试作为 JSON 解析（SDK 可能已经转换）
                return response.json()
            except Exception:
                # 如果无法解析为 JSON，返回原始内容
                try:
                    return {"content": response.content.decode("utf-8", errors="replace")}
                except Exception:
                    return {
                        "content_type": content_type,
                        "content_length": len(response.content),
                        "raw_content_preview": response.content[:100].hex() if len(response.content) > 0 else None,
                    }
    
    def get(self, path: str, params: dict[str, Any] | None = None, **kwargs: Any) -> dict[str, Any]:
        """GET 请求"""
        clean_path = path.lstrip("/")
        response = self.sdk_client.fetch(clean_path, method="GET", queryParams=self._normalize_params(params))
        return self._handle_response(response)
    
    def post(self, path: str, json: dict[str, Any] | None = None, **kwargs: Any) -> dict[str, Any]:
        """POST 请求"""
        clean_path = path.lstrip("/")
        response = self.sdk_client.fetch(clean_path, method="POST", data=json)
        return self._handle_response(response)
    
    def patch(self, path: str, json: dict[str, Any] | None = None, **kwargs: Any) -> dict[str, Any]:
        """PATCH 请求"""
        clean_path = path.lstrip("/")
        response = self.sdk_client.fetch(clean_path, method="PATCH", data=json)
        return self._handle_response(response)
    
    def delete(self, path: str, **kwargs: Any) -> dict[str, Any]:
        """DELETE 请求"""
        clean_path = path.lstrip("/")
        response = self.sdk_client.fetch(clean_path, method="DELETE")
        return self._handle_response(response)
    
    
    def close(self) -> None:
        """关闭客户端"""
        # SDK 客户端会自动处理
        pass

