"""
Helper utilities to work with indexed data. (content-doc/schema-api)
"""

from typing import List, Type, AsyncGenerator, Tuple, Generator, Sequence

import aiohttp

from clarabot_nano.common.solr.rest import nano_query_get, preparse_solr_response, extract_query_response


class SolrRequestFailed(Exception):
    pass


async def query_iter_docs(
    session: aiohttp.ClientSession,
    solr_query_url: str,
    solr_auth_header: str,
    query_expr: str,
    sort: str,
    fields: str,
    rows: int,
    exc_cls: Type[Exception] = SolrRequestFailed,
    filter_queries: Sequence[str] = None,
) -> AsyncGenerator[List[dict], None]:
    """
    Run a solr query in an asynchronous generator until it is exhausted.
    """
    url_params = [
        ("defType", "lucene"),
        ("q", query_expr),
        ("sort", sort),
        ("fl", fields),
        ("rows", rows),
    ]
    if filter_queries:
        for filter_query in filter_queries:
            url_params.append(("fq", filter_query))
    url_params.append(("cursorMark", "*"))
    while True:
        async with nano_query_get(session, solr_query_url, solr_auth_header, url_params) as r:
            result, success = await preparse_solr_response(r)
            if not success:
                raise exc_cls(f"Query failed\n{result}")
        q = extract_query_response(result)
        if not q["docs"]:
            break
        yield q["docs"]
        url_params[-1] = ("cursorMark", q.get("nextCursorMark"))


def decompose_docs_by_parent_accessor(
    parent_accessor_path: str, raw_docs: List[dict]
) -> Generator[Tuple[str, dict], None, None]:
    """
    Decompose all references to the documents in their accessors into a list.
    Also collect the names that the document resides in the parent_path.
    """
    for doc in raw_docs:
        found = False
        for acc in doc["accessors"]:
            parent, _, name = acc.rpartition("/")
            if parent == parent_accessor_path and name:
                found = True
                yield name, doc
        if not found:
            # TODO: INCON-ACCS this should not happen, but prepare a suitable handle for it anyways?
            raise Exception("Solr document has no matching accessor for preparation")
