import libra
from urllib.parse import unquote
from libra_parse_utils import get_query_data, is_intrasearch, is_long_click


class Session:
    def __init__(self, uid, session_id, timestamp, scope, zone):
        self.uid = uid
        self.session_id = session_id
        self.session_timestamp = timestamp
        self.scope = scope
        self.zone = zone
        self.requests_count = 0
        self.results_count = 0
        self.click_count = 0
        self.long_click_count = 0
        self.top3_click_count = 0
        self.top3_long_click_count = 0
        self.click_count_on_0 = 0
        self.click_count_on_1 = 0
        self.click_count_on_2 = 0
        self.click_count_on_3 = 0
        self.click_count_on_4 = 0


def get_req_ts(request):
    # Получаем время ReqId, потому что в нём хранится более точное значение в микросекундах
    return int(request.ReqId.split('-')[0])


def parse_clicks(blockstat_path, utils_path='', session_threshold=499999):
    """
    :param blockstat_path: ссылка на путь к файл blockstat.dict (нужен для работы библиотеки libra)
    :param utils_path: ссылка на путь к файл с утилитами для парсинга
    :param session_threshold: порог, при привышении которого запрос считается запросом из
        другой сессии, указывается в микросекундах
    """
    def libra_callable(uid, recs):
        requests = libra.ParseSessionWithFat(recs, blockstat_path)
        sessions_by_zone = {}
        last_request = None
        for request in sorted(requests, key=lambda a: a.ReqId):
            if not is_intrasearch(request):
                continue
            data = get_query_data(request)
            if not data or data['scope'] != 'suggest':
                continue
            if not last_request or (get_req_ts(request) - get_req_ts(last_request)) > session_threshold:
                yield from sessions_by_zone.values()
                sessions_by_zone = {}
            if data['zone'] not in sessions_by_zone:
                sessions_by_zone[data['zone']] = Session(
                    uid=uid,
                    session_id=request.ReqId,
                    timestamp=get_req_ts(request),
                    scope=data['scope'],
                    zone=data['zone'],
                )
            session = sessions_by_zone[data['zone']]
            clicks = {}
            for number, click in enumerate(request.GetClicks()):
                clicks[unquote(click.Url)] = {'dwell_time': click.DwellTime}
            results_count = 0
            for block in request.GetMainBlocks():
                for ch in block.GetChildren():
                    results_count += 1
                    click = clicks.get(ch.Url) or {}
                    if click:
                        session.click_count += 1
                        if is_long_click(click):
                            session.long_click_count += 1
                        if ch.Position < 3:
                            session.top3_click_count += 1
                            if is_long_click(click):
                                session.top3_long_click_count += 1
                        # В саджесте в шапках по умолчанию 5 позиций, считаем ctr только для них.
                        # Номера позиций начинаются с нуля.
                        if ch.Position < 5:
                            ctr_name = 'click_count_on_%s' % ch.Position
                            setattr(session, ctr_name, getattr(session, ctr_name, 0) + 1)
            session.requests_count += 1
            session.results_count = max(session.results_count, results_count)
            last_request = request
        yield from sessions_by_zone.values()
    return libra_callable
