import logging
import time
from logstash_async.handler import AsynchronousLogstashHandler
from logstash_async.formatter import LogstashFormatter
from egune.interfaces import ActorMessage, ApiRequest, Command, Interface, UserMessage
from typing import Callable, Dict, Any, List
import traceback
import json


logger = logging.getLogger('')


def init_logger(config):
    global logger
    logger = logging.getLogger(config["name"])
    logger.setLevel(logging.INFO)
    logstash_formatter = LogstashFormatter(message_type=f"egune-{config['name']}")
    logstash_handler = AsynchronousLogstashHandler(config["host"], config["port"], None)
    logstash_handler.setFormatter(logstash_formatter)
    logger.addHandler(logstash_handler)
    logger.info(f"Started {config['name']}", extra={
        "log_event": "system started"
    })


def log_request(request_name, input_prep=None, output_prep=None):
    def ultra_wrapped(func):
        def wrapped(data):
            s = time.time()
            original_input = data
            try:
                if input_prep is not None:
                    data = input_prep(data)
                if isinstance(data, tuple):
                    result = func(*data)
                else:
                    result = func(data)
                if output_prep is not None:
                    result = output_prep(result)
                logger.info("Processed", extra={
                    "log_event": request_name,
                    "process_input": original_input,
                    "process_output": result,
                    "time": time.time() - s
                })
                return result
            except Exception as e:
                logger.error("Failed", extra={
                    "log_event": request_name + ":Failed",
                    "process_input": original_input,
                    "process_output": traceback.format_exc(),
                    "time": time.time() - s
                })
                return e
        return wrapped
    return ultra_wrapped


def log(extra):
    logger.info("custom", extra=extra)
