"""ES 操作工具."""
from __future__ import annotations

from .connections import get_es_client, get_es_ops, get_es_version, get_safety


def _check_read_only() -> None:
    """检查是否为只读模式."""
    safety = get_safety()
    if safety.read_only:
        raise ValueError("当前为只读模式，拒绝执行写操作")


def _check_delete_index() -> None:
    """检查是否允许删除索引."""
    safety = get_safety()
    if not safety.allow_delete_index:
        raise ValueError("当前环境不允许删除索引")


def _check_create_index() -> None:
    """检查是否允许创建索引."""
    safety = get_safety()
    if not safety.allow_create_index:
        raise ValueError("当前环境不允许创建索引")


def es_search(
    index: str,
    query: dict | None = None,
    size: int = 10,
    from_: int = 0,
) -> dict:
    """搜索文档 (from/size 分页).

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    ops = get_es_ops()
    safety = get_safety()

    # 限制大小
    if size > safety.max_search_size:
        size = safety.max_search_size

    result = ops.search(
        index=index,
        query=query,
        size=size,
        from_=from_,
    )

    return {
        "hits": result.hits,
        "total": result.total,
        "truncated": result.truncated,
    }


def es_scroll(
    index: str,
    query: dict | None = None,
    size: int = 100,
    scroll: str = "5m",
) -> dict:
    """滚动查询 (首次调用).

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    ops = get_es_ops()

    result = ops.scroll(
        index=index,
        query=query,
        size=size,
        scroll=scroll,
    )

    return {
        "hits": result.hits,
        "scroll_id": result.scroll_id,
        "took_ms": result.took_ms,
    }


def es_scroll_next(scroll_id: str, scroll: str = "5m") -> dict:
    """滚动查询下一页.

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    ops = get_es_ops()

    result = ops.scroll_next(
        scroll_id=scroll_id,
        scroll=scroll,
    )

    return {
        "hits": result.hits,
        "scroll_id": result.scroll_id,
        "took_ms": result.took_ms,
    }


def es_scroll_clear(scroll_id: str) -> dict:
    """清除滚动上下文.

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    ops = get_es_ops()
    ops.scroll_clear(scroll_id=scroll_id)
    return {"success": True, "message": "滚动上下文已清除"}


def es_index_doc(
    index: str,
    doc: dict,
    id_: str | None = None,
) -> dict:
    """索引文档.

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    _check_read_only()
    ops = get_es_ops()

    doc_id = ops.index_doc(
        index=index,
        doc=doc,
        id_=id_,
    )

    return {"success": True, "_id": doc_id}


def es_update_doc(
    index: str,
    id_: str,
    doc: dict,
) -> dict:
    """更新文档.

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    _check_read_only()
    ops = get_es_ops()

    ops.update_doc(
        index=index,
        id_=id_,
        doc=doc,
    )

    return {"success": True, "message": f"文档 {id_} 已更新"}


def es_delete_doc(
    index: str,
    id_: str,
) -> dict:
    """删除文档.

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    _check_read_only()
    ops = get_es_ops()

    ops.delete_doc(
        index=index,
        id_=id_,
    )

    return {"success": True, "message": f"文档 {id_} 已删除"}


def es_bulk(
    operations: list[dict],
    refresh: bool = False,
) -> dict:
    """批量操作.

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    _check_read_only()
    ops = get_es_ops()

    result = ops.bulk(
        operations=operations,
        refresh=refresh,
    )

    return {
        "succeeded": result.succeeded,
        "failed": result.failed,
        "errors": result.errors,
    }


def es_create_index(
    index: str,
    mappings: dict | None = None,
    settings: dict | None = None,
) -> dict:
    """创建索引.

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    _check_read_only()
    _check_create_index()
    ops = get_es_ops()

    ops.create_index(
        index=index,
        mappings=mappings,
        settings=settings,
    )

    return {"success": True, "message": f"索引 {index} 已创建"}


def es_delete_index(index: str) -> dict:
    """删除索引.

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    _check_read_only()
    _check_delete_index()
    ops = get_es_ops()

    success = ops.delete_index(index=index)

    if success:
        return {"success": True, "message": f"索引 {index} 已删除"}
    else:
        return {"success": False, "message": f"索引 {index} 不存在"}


def es_index_exists(index: str) -> dict:
    """检查索引是否存在.

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    ops = get_es_ops()

    exists = ops.index_exists(index=index)

    return {"exists": exists, "index": index}


def es_get_index_mapping(index: str) -> dict:
    """获取索引 mapping.

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    ops = get_es_ops()

    mapping = ops.get_index_mapping(index=index)

    return {"mapping": mapping}


def es_list_indices() -> dict:
    """列出所有索引.

    根据当前连接的 ES 版本自动路由到对应实现。
    """
    ops = get_es_ops()

    indices = ops.list_indices()

    return {"indices": indices, "count": len(indices)}
