import logging

from cached_property import cached_property
from ylog.context import put_to_context, pop_from_context

from .base import BaseAsyncContext
from .collector import ContextCollector


class HttpLogContext(BaseAsyncContext):
    TAG = 'http'

    def __init__(self, request, **kwargs):
        self.request = request
        super().__init__(**kwargs)

    def _before_exit(self):
        super()._before_exit()
        pop_from_context('response')

    def log_after_execution(self, context):
        user = context.get('user') or {}
        request = context.get('request') or {}
        response = context.get('response')

        if not response:
            response = {
                'status_code': 500
            }
            put_to_context('response', response)

        logging.info(
            '%s %s>%s: %s (took %.3f ms)',
            user.get('login', ''),
            request.get('method'),
            response.get('status_code'),
            request.get('path'),
            context.get('execution_time'),
        )

    @cached_property
    def collector(self):
        return ContextCollector(request=self.request)


http_log_context = HttpLogContext


async def log_context_middleware(request, call_next):
    with http_log_context(request):
        response = await call_next(request)
        put_to_context('response', {
            'status_code': response.status_code
        })
    return response
