"""Magic-API HTTP 客户端封装。"""

from __future__ import annotations

import json
import uuid
from typing import Any, Dict, Mapping, MutableMapping, Optional

import requests

from magicapi_mcp.settings import MagicAPISettings, DEFAULT_SETTINGS
from magicapi_tools.logging_config import get_logger

# 获取HTTP客户端的logger
logger = get_logger('utils.http_client')


def _default_headers() -> dict[str, str]:
    return {
        "Content-Type": "application/json",
        "Accept": "application/json",
        "User-Agent": "magicapi-tools/1.0",
    }


class MagicAPIHTTPClient:
    """简化 Magic-API 调用的 HTTP 客户端。"""

    def __init__(self, settings: MagicAPISettings | None = None, client_id: str | None = None) -> None:
        self.settings = settings or DEFAULT_SETTINGS
        self.client_id = client_id or uuid.uuid4().hex
        self.session = requests.Session()
        self.session.headers.update(_default_headers())
        self.settings.inject_auth(self.session.headers)


        if self.settings.auth_enabled and self.settings.username and self.settings.password:
            self._login()

    def _login(self) -> bool:
        payload = {
            "username": self.settings.username,
            "password": self.settings.password,
        }
        try:
            response = self.session.post(
                f"{self.settings.base_url}/magic/web/login",
                json=payload,
                timeout=self.settings.timeout_seconds,
            )
            if response.status_code == 200:
                try:
                    data = response.json()
                except json.JSONDecodeError:
                    return False
                return data.get("code") == 1
            return False
        except requests.RequestException:
            return False

    def _build_full_paths(self, tree_data: Dict[str, Any]) -> Dict[str, Any]:
        """为资源树中的每个节点构建完整路径"""
        def build_path_recursive(node: Dict[str, Any], parent_path: str = "") -> Dict[str, Any]:
            """递归构建节点的全路径"""
            node_copy = dict(node)  # 复制节点避免修改原数据

            # 获取当前节点的路径信息
            node_info = node_copy.get("node", {})
            current_path = node_info.get("path", "")

            # 构建完整路径
            if parent_path and current_path:
                full_path = f"{parent_path}/{current_path}"
            elif current_path:
                full_path = current_path
            else:
                full_path = parent_path

            # 清理路径（去除多余的斜杠）
            full_path = full_path.strip("/")
            while "//" in full_path:
                full_path = full_path.replace("//", "/")

            # 为节点添加full_path信息
            if node_info:
                node_info["full_path"] = f"/{full_path}" if full_path else "/"
                node_copy["node"] = node_info

            # 递归处理子节点
            if "children" in node_copy and node_copy["children"]:
                new_children = []
                for child in node_copy["children"]:
                    new_child = build_path_recursive(child, full_path)
                    new_children.append(new_child)
                node_copy["children"] = new_children

            return node_copy

        # 处理整个树结构
        result = {}
        for key, subtree in tree_data.items():
            if isinstance(subtree, dict) and "children" in subtree:
                # 这是一个分组节点
                result[key] = build_path_recursive(subtree)
            else:
                # 直接复制非树形数据
                result[key] = subtree

        return result

    def resource_tree(self) -> tuple[bool, Any]:
        url = f"{self.settings.base_url}/magic/web/resource"
        logger.debug(f"HTTP请求: POST {url}")

        try:
            response = self.session.post(url, timeout=self.settings.timeout_seconds)
            logger.debug(f"HTTP响应: {response.status_code}, 耗时: {response.elapsed.total_seconds()}s")

            if response.status_code != 200:
                logger.error(f"获取资源树失败: HTTP {response.status_code}")
                logger.error(f"  请求URL: {url}")
                logger.error(f"  响应内容: {response.text[:500]}...")
                return False, {
                    "code": response.status_code,
                    "message": "获取资源树失败",
                    "detail": response.text,
                }

            payload = response.json()
            logger.debug(f"  响应数据: code={payload.get('code')}, message={payload.get('message')}")

            if payload.get("code") != 1:
                logger.error(f"获取资源树失败: {payload.get('message', '接口返回异常')}")
                logger.error(f"  响应数据: {payload}")
                return False, {
                    "code": payload.get("code", -1),
                    "message": payload.get("message", "接口返回异常"),
                }

            data = payload.get("data", {})

            # 为资源树添加完整路径信息
            data_with_paths = self._build_full_paths(data)


            return True, data_with_paths

        except requests.RequestException as exc:
            logger.error(f"获取资源树网络异常: {exc}")
            logger.error(f"  请求URL: {url}")
            import traceback
            logger.debug(f"  异常堆栈: {traceback.format_exc()}")
            return False, {
                "code": "network_error",
                "message": "请求资源树出现异常",
                "detail": str(exc),
            }

    def api_detail(self, file_id: str) -> tuple[bool, Any]:
        url = f"{self.settings.base_url}/magic/web/resource/file/{file_id}"
        logger.debug(f"HTTP请求: GET {url}")
        logger.debug(f"  文件ID: {file_id}")

        try:
            response = self.session.get(url, timeout=self.settings.timeout_seconds)
            logger.debug(f"HTTP响应: {response.status_code}, 耗时: {response.elapsed.total_seconds()}s")

            if response.status_code != 200:
                logger.error(f"获取API详情失败: HTTP {response.status_code}")
                logger.error(f"  请求URL: {url}")
                logger.error(f"  文件ID: {file_id}")
                logger.error(f"  响应内容: {response.text[:1000]}...")
                logger.debug(f"  响应头: {dict(response.headers)}")

                return False, {
                    "code": response.status_code,
                    "message": "获取接口详情失败",
                    "detail": response.text,
                    "url": url,
                    "file_id": file_id,
                }

            payload = response.json()
            logger.debug(f"  响应数据: code={payload.get('code')}, message={payload.get('message')}")

            if payload.get("code") != 1:
                error_code = payload.get("code", -1)
                error_message = payload.get("message", "接口返回异常")
                error_data = payload.get("data")

                logger.error(f"获取API详情失败: {error_message}")
                logger.error(f"  请求URL: {url}")
                logger.error(f"  文件ID: {file_id}")
                logger.error(f"  错误代码: {error_code}")
                logger.error(f"  错误数据: {error_data}")
                logger.debug(f"  完整响应: {payload}")

                return False, {
                    "code": error_code,
                    "message": error_message,
                    "data": error_data,
                    "url": url,
                    "file_id": file_id,
                }

            data = payload.get("data")
            if data is None:
                logger.warning(f"API详情数据为空: {file_id}")
                logger.warning(f"  请求URL: {url}")
                logger.debug(f"  响应: {payload}")

            logger.info(f"获取API详情成功: {file_id}")
            return True, data

        except requests.RequestException as exc:
            logger.error(f"获取API详情网络异常: {exc}")
            logger.error(f"  文件ID: {file_id}")
            logger.error(f"  请求URL: {url}")
            import traceback
            logger.debug(f"  异常堆栈: {traceback.format_exc()}")

            return False, {
                "code": "network_error",
                "message": "请求接口详情异常",
                "detail": str(exc),
                "file_id": file_id,
                "url": url,
            }

    def call_api(
        self,
        method: str,
        path: str,
        params: Optional[Mapping[str, Any]] = None,
        data: Optional[Any] = None,
        headers: Optional[Mapping[str, str]] = None,
        timeout: Optional[float] = None,
    ) -> tuple[bool, Any]:
        method = method.upper()
        if not path.startswith("/"):
            path = f"/{path}"

        url = f"{self.settings.base_url}{path}"

        logger.debug(f"HTTP请求: {method} {url}")
        if params:
            logger.debug(f"  查询参数: {params}")
        if data:
            if isinstance(data, (dict, list)):
                logger.debug(f"  请求体(JSON): {json.dumps(data, ensure_ascii=False)[:1000]}...")
            elif isinstance(data, str) and len(data) < 200:
                logger.debug(f"  请求体: {data}")
            else:
                logger.debug(f"  请求体: ({len(str(data))} 字符)")

        provided_headers = dict(headers or {})
        request_headers: MutableMapping[str, str] = {}
        request_headers["Magic-Request-Client-Id"] = provided_headers.get("Magic-Request-Client-Id", self.client_id)
        request_headers["Magic-Request-Script-Id"] = provided_headers.get("Magic-Request-Script-Id", uuid.uuid4().hex)
        request_headers["Magic-Request-Breakpoints"] = provided_headers.get("Magic-Request-Breakpoints", "")

        # 兼容旧头信息
        if "X-MAGIC-CLIENT-ID" in provided_headers:
            request_headers["X-MAGIC-CLIENT-ID"] = provided_headers["X-MAGIC-CLIENT-ID"]
        if "X-MAGIC-SCRIPT-ID" in provided_headers:
            request_headers["X-MAGIC-SCRIPT-ID"] = provided_headers["X-MAGIC-SCRIPT-ID"]

        for key, value in provided_headers.items():
            if key not in request_headers:
                request_headers[key] = value

        self.settings.inject_auth(request_headers)
        request_headers.setdefault("Magic-Token", self.settings.token or "unauthorization")
        if "Magic-Request-Breakpoints" in request_headers:
            request_headers.setdefault("magic-request-breakpoints", request_headers["Magic-Request-Breakpoints"])

        logger.debug(f"  请求头: {dict(request_headers)}")

        request_kwargs: dict[str, Any] = {
            "params": params,
            "headers": request_headers,
            "timeout": timeout or self.settings.timeout_seconds,
        }

        if isinstance(data, (dict, list)):
            request_kwargs["json"] = data
        elif isinstance(data, str):
            request_kwargs["data"] = data
        elif data is not None:
            request_kwargs["data"] = json.dumps(data)

        try:
            response = self.session.request(method, url, **request_kwargs)
            logger.debug(f"HTTP响应: {response.status_code}, 耗时: {response.elapsed.total_seconds()}s")

            content_type = response.headers.get("Content-Type", "")
            if "application/json" in content_type:
                try:
                    body = response.json()
                    logger.debug(f"  响应体(JSON): {json.dumps(body, ensure_ascii=False)[:1000]}...")
                except json.JSONDecodeError:
                    body = response.text
                    logger.debug(f"  响应体(文本): {body[:1000]}...")
            else:
                body = response.text
                logger.debug(f"  响应体: {body[:1000]}...")

            success = response.status_code < 400
            if not success:
                logger.error(f"API调用失败: HTTP {response.status_code}")
                logger.error(f"  响应体: {body}")

            result = {
                "status": response.status_code,
                "headers": dict(response.headers),
                "body": body,
            }
            if not success:
                result.setdefault("code", response.status_code)
                result.setdefault("message", f"HTTP {response.status_code}")

            return success, result
        except requests.RequestException as exc:
            logger.error(f"API调用网络异常: {exc}")
            logger.error(f"  请求: {method} {url}")
            import traceback
            logger.debug(f"  异常堆栈: {traceback.format_exc()}")

            return False, {
                "code": "network_error",
                "message": "调用 Magic-API 接口失败",
                "detail": str(exc),
            }


__all__ = ["MagicAPIHTTPClient"]
