from typing import Sequence, Tuple, Callable

from elasticsearch import Elasticsearch
from redis.client import StrictRedis

from apiserver.utilities.dicts import nested_get
from .event_common import EventType
from .metric_events_iterator import MetricEventsIterator, VariantState


class MetricDebugImagesIterator(MetricEventsIterator):
    def __init__(self, redis: StrictRedis, es: Elasticsearch):
        super().__init__(redis, es, EventType.metrics_image)

    def _get_extra_conditions(self) -> Sequence[dict]:
        return [{"exists": {"field": "url"}}]

    def _get_variant_state_aggs(self) -> Tuple[dict, Callable[[dict, VariantState], None]]:
        aggs = {
            "urls": {
                "terms": {
                    "field": "url",
                    "order": {"max_iter": "desc"},
                    "size": 1,  # we need only one url from the most recent iteration
                },
                "aggs": {
                    "max_iter": {"max": {"field": "iter"}},
                    "iters": {
                        "top_hits": {
                            "sort": {"iter": {"order": "desc"}},
                            "size": 2,  # need two last iterations so that we can take
                            # the second one as invalid
                            "_source": "iter",
                        }
                    },
                },
            }
        }

        def fill_variant_state_data(variant_bucket: dict,  state: VariantState):
            """If the image urls get recycled then fill the last_invalid_iteration field"""
            top_iter_url = nested_get(variant_bucket, ("urls", "buckets"))[0]
            iters = nested_get(top_iter_url, ("iters", "hits", "hits"))
            if len(iters) > 1:
                state.last_invalid_iteration = nested_get(iters[1], ("_source", "iter"))

        return aggs, fill_variant_state_data

    def _process_event(self, event: dict) -> dict:
        return event

    def _get_same_variant_events_order(self) -> dict:
        return {"url": {"order": "desc"}}