# -*- coding: utf-8 -*-
import logging
import json
import ylog

from django.conf import settings
from ylog.context import get_log_context


class EscapedFileHandler(ylog.WatchedFileHandler):
    def format(self, *args, **kwargs):
        msg = super(EscapedFileHandler, self).format(*args, **kwargs)
        if isinstance(msg, str):
            msg = msg.encode('utf-8')
        return msg.encode('string_escape')


def flat_dict(d, parent_keys, result):
    if isinstance(d, dict):
        for key, value in d.items():
            flat_dict(value, parent_keys + [key], result)
    else:
        result.append(('.'.join(parent_keys), d))


def dict_to_string(d, delim='; '):
    context = []
    flat_dict(d, [], context)
    return delim.join(
        f'{key}={value}'
        for key, value in context
    )


class ContextFormatter(ylog.context.ContextFormatter):
    def serialize_context(self):
        return dict_to_string({
            key: value[-1]
            for key, value in self.thread_data.logging_context.items()
        })


class JsonFormatter(logging.Formatter):
    pretty_params = {'indent': 2, 'sort_keys': True, 'ensure_ascii': False}

    def format(self, record):
        context = get_log_context() or {}
        request = context.get('request') or {}
        user = context.get('user') or {}

        log_data = {
            'message': record.getMessage(),
            'levelStr': record.levelname,
            'loggerName': record.name,
            'level': record.levelno,
            'request_id': request.get('id'),
            'user_id': user.get('uid'),
            '@fields': {
                'context': context,
                'std': {
                    'orig_msg': record.msg,
                },
            },
        }

        if record.exc_info:
            exc = logging.Formatter.formatException(self, record.exc_info)
            log_data['stackTrace'] = exc

        params = {}
        if settings.PRETTY_LOGS:
            params = self.pretty_params
        return json.dumps(log_data, **params)
