# -*- coding: UTF-8 -*-
import json
import traceback

import redis
from django.conf import settings
from django.http import HttpResponse

from api.models import City
from doctor.models import TrafficStat
from rpc.context import get_rpc_remote_invoker
from search.utils.es import health, talos_es_health


def render_json(wrapper):
    def wrappered(*args, **argv):
        json_data = wrapper(*args, **argv)
        data = HttpResponse(json.dumps(json_data), content_type='application/json')
        return data

    return wrappered


def check_redis_url(redis_url):
    redis_client = redis.StrictRedis.from_url(redis_url)
    redis_client.set("test", "test")


def check_redis_dict(config):
    redis_client = redis.StrictRedis(**config)
    redis_client.set("test", "test")


def _check_es():
    error = {}
    es_ok = True
    try:
        res = health()
        if res['status'] == 'green':
            es_ok = True
        else:
            error = {
                "elasticsearch": res,
            }
            es_ok = False
    except:
        error = {
            "elasticsearch": traceback.format_exc()
        }
        es_ok = False

    return es_ok, error


def _check_talos_es():
    error = {}
    try:
        res = talos_es_health()
        if res['status'] == 'green':
            es_ok = True
        else:
            error = {
                "elasticsearch": res,
            }
            es_ok = False
    except:
        error = {
            "elasticsearch": traceback.format_exc()
        }
        es_ok = False

    return es_ok, error


def _check_mysql():
    error = {}
    mysql_ok = True
    try:
        item = City.objects.last()
        TrafficStat.objects.last()  # 该model 不在zhengxing库
    except:
        mysql_ok = False
        error = {
            "mysql": traceback.format_exc()
        }
    return mysql_ok, error


def _check_slave_mysql():
    error = {}
    slave_ok = True
    try:
        slave_db = settings.SLAVE_DB_NAME
        item = City.objects.using(slave_db).last()
    except:
        slave_ok = False
        error = {
            "slave_mysql": traceback.format_exc()
        }
    return slave_ok, error


def _check_redis():
    error = {}
    redis_ok = True
    try:
        check_redis_dict(settings.DEFAULT_REDIS)
        check_redis_dict(settings.REDIS['doctor'])
        check_redis_dict(settings.REDIS['view'])
        # check_redis_dict(settings.REDIS['user_cache'])
        check_redis_dict(settings.REDIS['diary'])
        check_redis_dict(settings.REDIS['page_cache'])
        check_redis_dict(settings.REDIS['coupon_gift'])
        check_redis_dict(settings.REDIS['game'])
        # check_redis_dict(settings.REDIS['social_cache'])
        # check_redis_dict(settings.REDIS['vote_cache'])
        check_redis_dict(settings.LIVE_REDIS)
        check_redis_url(settings.BROKER_URL)
    except:
        redis_ok = False
        error = {
            "redis": traceback.format_exc()
        }
    return redis_ok, error


@render_json
def statuses(request):
    ok = True
    errors = {}
    resp = {
        'ok': ok,
        'errors': errors
    }
    # check es

    es_ok, error = _check_es()
    if not es_ok:
        errors.update(error)
    # check redis
    mysql_ok, error = _check_mysql()
    if not mysql_ok:
        errors.update(error)

    slave_ok, error = _check_slave_mysql()
    if not slave_ok:
        errors.update(error)

    redis_ok, error = _check_redis()
    if not redis_ok:
        errors.update(error)

    resp['ok'] = es_ok and mysql_ok and slave_ok and redis_ok

    if request.GET.get('self_check_only'):
        # dont check other rpc services
        return resp

    # check whole system status
    rpc_flag, rpc_result = check_rpc_connect()
    resp['ok'] = resp['ok'] and rpc_flag
    resp['errors'].update(rpc_result)

    return resp


def check_rpc_connect():
    rpc_invoker = get_rpc_remote_invoker()
    result = rpc_invoker.check_rpcd_connect()
    for r in result:
        if result[r] != u'ok':
            return False, result
    return True, result
