"""
Elasticsearch 连接与 API 封装（elasticsearch-py）。
"""
from __future__ import annotations

import contextlib
from typing import Any, Generator

from elasticsearch import Elasticsearch

from .config import ConnectionConfig, SafetyConfig


def get_connection_config(
    profile: str | None,
    default: ConnectionConfig,
    connection_map: dict[str, ConnectionConfig],
) -> ConnectionConfig:
    if not (profile or "").strip():
        return default
    key = (profile or "").strip()
    if key not in connection_map:
        raise ValueError(f"未知的 connection profile: {profile}，可用: {', '.join(sorted(connection_map))}")
    return connection_map[key]


@contextlib.contextmanager
def connect(
    config: ConnectionConfig,
    safety: SafetyConfig,
) -> Generator[Elasticsearch, None, None]:
    scheme = "https" if config.use_ssl else "http"
    url = f"{scheme}://{config.host}:{config.port}"
    auth = (config.user, config.password) if config.user else None
    # ES 7.x 不支持 application/vnd.elasticsearch+json，需用 application/json
    headers = None
    if config.skip_product_check:
        headers = {"Content-Type": "application/json", "Accept": "application/json"}
    client = Elasticsearch(
        [url],
        basic_auth=auth,
        request_timeout=safety.request_timeout,
        headers=headers,
    )
    if config.skip_product_check:
        client._verified_elasticsearch = True  # 兼容 OpenSearch/未带 X-Elastic-Product 的服务
    try:
        yield client
    finally:
        client.close()


def list_indices(client: Elasticsearch, pattern: str = "*") -> list[dict[str, Any]]:
    """列出索引，支持 pattern。返回 [{"name": "...", "docs_count": ...}, ...]"""
    cat = client.cat.indices(index=pattern, format="json")
    if not cat:
        return []
    return [{"name": x.get("index", ""), "docs_count": x.get("docs.count", "0"), "store.size": x.get("store.size", "")} for x in cat]


def get_mapping(client: Elasticsearch, index: str) -> dict[str, Any]:
    """获取索引 mapping。"""
    return client.indices.get_mapping(index=index) or {}


def execute_request(
    client: Elasticsearch,
    method: str,
    path: str,
    body: dict[str, Any] | None = None,
) -> dict[str, Any]:
    """执行单条 REST 请求。path 如 /index/_search，不含 host。"""
    # elasticsearch-py: client.transport.perform_request(method, path, body=body)
    return client.transport.perform_request(method, path, body=body)
