"""API 测试关键字"""

import json
from typing import Any, Dict, Optional

from .request_handler import RequestHandler
from ..reference import INFO, set_element_value, get_element_value


class ApiKeyword:
    """API 测试关键字

    提供 API 测试的关键字方法。
    """

    def __init__(self, request_handler: RequestHandler = None):
        """初始化 API 关键字

        Args:
            request_handler: 请求处理器
        """
        self._handler = request_handler or RequestHandler()

    def api_set_base_url(self, *, content: str) -> None:
        """设置基础 URL

        Args:
            content: 基础 URL
        """
        self._handler._base_url = content
        INFO(f"设置基础 URL: {content}")

    def api_set_header(self, *, content: str) -> None:
        """设置请求头

        Args:
            content: JSON 格式的请求头 {"key": "value"}
        """
        headers = json.loads(content)
        self._handler.set_default_headers(headers)
        INFO(f"设置请求头: {list(headers.keys())}")

    def api_get(self, *, content: str, key: str = None) -> Dict[str, Any]:
        """GET 请求

        Args:
            content: URL 或 JSON 配置 {"url": "...", "params": {...}}
            key: 响应缓存键名

        Returns:
            Dict: 响应数据
        """
        if content.startswith('{'):
            config = json.loads(content)
            url = config.get('url', '')
            params = config.get('params')
            headers = config.get('headers')
            response = self._handler.get(url, params=params, headers=headers)
        else:
            response = self._handler.get(content)

        if key:
            set_element_value(key, response)

        return response

    def api_post(self, *, content: str, key: str = None) -> Dict[str, Any]:
        """POST 请求

        Args:
            content: JSON 配置 {"url": "...", "data": {...}}
            key: 响应缓存键名

        Returns:
            Dict: 响应数据
        """
        config = json.loads(content)
        url = config.get('url', '')
        data = config.get('data')
        json_data = config.get('json')
        headers = config.get('headers')

        response = self._handler.post(url, data=data, json_data=json_data, headers=headers)

        if key:
            set_element_value(key, response)

        return response

    def api_put(self, *, content: str, key: str = None) -> Dict[str, Any]:
        """PUT 请求

        Args:
            content: JSON 配置
            key: 响应缓存键名

        Returns:
            Dict: 响应数据
        """
        config = json.loads(content)
        url = config.get('url', '')
        data = config.get('data')
        json_data = config.get('json')
        headers = config.get('headers')

        response = self._handler.put(url, data=data, json_data=json_data, headers=headers)

        if key:
            set_element_value(key, response)

        return response

    def api_delete(self, *, content: str, key: str = None) -> Dict[str, Any]:
        """DELETE 请求

        Args:
            content: URL 或 JSON 配置
            key: 响应缓存键名

        Returns:
            Dict: 响应数据
        """
        if content.startswith('{'):
            config = json.loads(content)
            url = config.get('url', '')
            headers = config.get('headers')
            response = self._handler.delete(url, headers=headers)
        else:
            response = self._handler.delete(content)

        if key:
            set_element_value(key, response)

        return response

    def api_status_assert(self, *, content: str) -> bool:
        """断言响应状态码

        Args:
            content: 期望的状态码

        Returns:
            bool: 断言结果
        """
        response = self._handler.last_response
        if not response:
            INFO("没有响应数据", "ERROR")
            return False

        expected = int(content)
        actual = response.get('status')
        result = actual == expected

        INFO(f"状态码断言: {actual} == {expected} -> {result}")
        return result

    def api_json_assert(self, *, content: str, path: str, mode: str = 'equals') -> bool:
        """断言响应 JSON 字段

        Args:
            content: 期望值
            path: JSON 路径 (如 "data.user.name")
            mode: 断言模式

        Returns:
            bool: 断言结果
        """
        response = self._handler.last_response
        if not response or 'json' not in response:
            INFO("没有 JSON 响应数据", "ERROR")
            return False

        # 获取实际值
        actual = self._get_json_value(response['json'], path)

        # 断言
        if mode == 'equals':
            result = str(actual) == content
        elif mode == 'contains':
            result = content in str(actual)
        elif mode == 'exists':
            result = actual is not None
        elif mode == 'not_exists':
            result = actual is None
        else:
            result = str(actual) == content

        INFO(f"JSON 断言: {path}='{actual}' {mode} '{content}' -> {result}")
        return result

    def api_extract_value(self, *, content: str, path: str) -> Any:
        """提取响应值并缓存

        Args:
            content: 缓存键名
            path: JSON 路径

        Returns:
            提取的值
        """
        response = self._handler.last_response
        if not response or 'json' not in response:
            INFO("没有 JSON 响应数据", "ERROR")
            return None

        value = self._get_json_value(response['json'], path)
        set_element_value(content, value)

        INFO(f"提取值: {content} = {path} -> {value}")
        return value

    def api_get_response(self, *, content: str) -> Optional[Dict[str, Any]]:
        """获取缓存的响应

        Args:
            content: 缓存键名

        Returns:
            响应数据
        """
        return get_element_value(content)

    def _get_json_value(self, data: Any, path: str) -> Any:
        """从 JSON 获取值

        Args:
            data: JSON 数据
            path: 路径 (支持点号和数组索引)

        Returns:
            值
        """
        keys = path.replace('[', '.').replace(']', '').split('.')
        value = data

        for key in keys:
            if not key:
                continue

            if isinstance(value, dict):
                value = value.get(key)
            elif isinstance(value, list) and key.isdigit():
                index = int(key)
                value = value[index] if 0 <= index < len(value) else None
            else:
                return None

            if value is None:
                return None

        return value
