from uuid import uuid4

from django.utils import translation
from django.utils.deprecation import MiddlewareMixin
from django.utils.translation.trans_real import (parse_accept_lang_header, language_code_re,
                                                 get_supported_language_variant)
from django_alive.middleware import AliveMiddleware as BaseAliveMiddleware
from ylog import context


class LogContextMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request_id = (request.GET.get('request_id') or
                      request.META.get('HTTP_X_REQ_ID') or
                      request.META.get('HTTP_X_REQUEST_ID') or
                      uuid4().hex)
        context.put_to_context('request_id', request_id)
        suggest_id = request.GET.get('X-Suggest-Session-Id')
        context.put_to_context('suggest_request_id', suggest_id)

    def exit_context(self):
        context.pop_from_context('request_id')

    def process_exception(self, *args, **kwargs):
        self.exit_context()

    def process_response(self, request, response):
        self.exit_context()
        return response


class AliveMiddleware(MiddlewareMixin, BaseAliveMiddleware):
    pass


class I18NMiddleware(MiddlewareMixin):
    """Дополнительный процессор для установки языка залогиненного пользователя
    в соответствии с блекбоксом
    """

    def process_request(self, request):
        lang = get_language_from_request(request)

        if lang is None:
            lang = 'en'
        if lang != 'ru':
            lang = 'en'
        translation.activate(lang)
        request.LANGUAGE_CODE = lang

    def process_response(self, request, response):
        language = translation.get_language()
        if 'Content-Language' not in response:
            response['Content-Language'] = language
        return response


def get_language_from_request(request):
    accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
    for accept_lang, unused in parse_accept_lang_header(accept):
        if accept_lang == '*':
            break

        if not language_code_re.search(accept_lang):
            continue

        try:
            return get_supported_language_variant(accept_lang)
        except LookupError:
            continue
    return None
