import time

import flask
import sepiida.environment
import sepiida.requests
import prometheus_client.core
import prometheus_client.exposition

REQUEST_LATENCY = prometheus_client.Histogram( # pylint: disable=unexpected-keyword-arg
    'request_latency_seconds', 'Flask Request Latency',
    ['service', 'method', 'endpoint'],
    namespace='sepiida',
)
REQUEST_COUNT = prometheus_client.Counter( # pylint: disable=unexpected-keyword-arg
    'flask_request_count', 'Flask Request Count',
    ['service', 'method', 'endpoint', 'http_status'],
    namespace='sepiida',
)
USER_SESSION_REQUEST_COUNT = prometheus_client.Counter( # pylint: disable=unexpected-keyword-arg
    'user_session_request_count', 'Requests Made By User Session',
    ['service', 'method', 'endpoint'],
    namespace='sepiida',
)
PRIVILEGED_SESSION_REQUEST_COUNT = prometheus_client.Counter( # pylint: disable=unexpected-keyword-arg
    'privileged_session_request_count', 'Requests Made by Privileged Session',
    ['service', 'method', 'endpoint'],
    namespace='sepiida',
)

def metrics():
    registry = prometheus_client.core.REGISTRY
    args = flask.request.args
    if 'name[]' in args:
        registry = registry.restricted_registry(args.getlist('name[]'))
    try:
        output = prometheus_client.exposition.generate_latest(registry)
    except Exception: # pylint: disable=broad-except
        return 500, 'error generating metric output', {}
    response = flask.make_response(output, 200)
    response.headers['Content-Type'] = prometheus_client.exposition.CONTENT_TYPE_LATEST
    return response

def before_request():
    flask.request.metrics = {
        'start'                         : time.time(),
    }

def after_request(response):
    # We may not have the metrics attribute if our response is generated by another before_request middleware
    if not hasattr(flask.request, 'metrics'):
        return response
    latency = time.time() - flask.request.metrics['start']
    settings = sepiida.environment.get()
    REQUEST_LATENCY.labels(
        settings.SERVER_NAME,
        flask.request.method,
        flask.request.path,
    ).observe(latency)
    REQUEST_COUNT.labels(
        settings.SERVER_NAME,
        flask.request.method,
        flask.request.path,
        response.status_code,
    ).inc()
    privileged_session_request_count = sepiida.requests.privileged_session_request_count()
    if privileged_session_request_count is not None:
        PRIVILEGED_SESSION_REQUEST_COUNT.labels( # pylint: disable=no-member
            settings.SERVER_NAME,
            flask.request.method,
            flask.request.path,
        ).inc(privileged_session_request_count)
    user_session_request_count = sepiida.requests.user_session_request_count()
    if user_session_request_count is not None:
        USER_SESSION_REQUEST_COUNT.labels( # pylint: disable=no-member
            settings.SERVER_NAME,
            flask.request.method,
            flask.request.path,
        ).inc(user_session_request_count)
    return response

def add_handler(app):
    app.route('/metrics/')(metrics)
    app.before_request(before_request)
    app.after_request(after_request)
