from django.http import HttpResponse
from django.http import HttpResponseServerError, HttpResponseBadRequest
from django.shortcuts import render_to_response

from .juggler.golovan import get_all_alerts_names
from .juggler.golovan import alert_service_from_name
from .juggler.golovan import alerts_by_ctype_service
from .juggler import checks_by_ctype_service
from .juggler.alerts import get_alerts
from .juggler.alerts import reformat_alerts_data
from .juggler.alerts import set_alert
from .juggler.alerts import change_alert
from .juggler.alerts import is_default_service
from .juggler.dm import get_alerts_conf
from .juggler.dm import logins_from_conf
from .juggler.dm import should_have_juggler
from .juggler.dm import alert_keys_from_conf
from .juggler.dm import patch_conf
from .juggler.dm import SIGNALS

from .cluster import alerts_commands as dm_alerts
from .cluster import get_cluster_data as cluster_data

from .people import is_saas_developer

from .helpers import service_ctypes

import json


def alerts_main():
    serv_ct_res = service_ctypes()
    if not serv_ct_res['success']:
        return HttpResponseServerError(json.dumps(serv_ct_res))
    serv_ct = serv_ct_res['serv_ct']
    checks_res = checks_by_ctype_service()
    if not checks_res['success']:
        return HttpResponseServerError(json.dumps(checks_res))
    checks_ct = checks_res['checks']
    gol_res = alerts_by_ctype_service()
    if not gol_res['success']:
        return HttpResponseServerError(json.dumps(gol_res))

    alerts_services = []
    unactual_services = []

    for ct, servs in checks_ct.items():
        for serv in servs:
            if serv in serv_ct.get(ct, []):
                alerts_services.append(serv)
            else:
                unactual_services.append(serv)
    for ct, servs in gol_res['alerts'].items():
        for serv in servs:
            if serv in serv_ct.get(ct, []):
                alerts_services.append(serv)
            else:
                unactual_services.append(serv)

    alerts_services = sorted(list(set(alerts_services)))
    unactual_services = list(set(unactual_services))

    return render_to_response('alerts_main.html', {'signals': SIGNALS(),
                                                   'services': alerts_services,
                                                   'unactuals': unactual_services})


def service_alerts(request):
    try:
        user = request.yauser.login
    except Exception as e:
        user = 'error: %s' % e
    service = request.GET.get('service', '')
    if not service:
        return alerts_main()
    alerts = get_alerts(host=request.GET.get('golem_host', ''), service=service)
    is_default = is_default_service(service)
    if is_default:
        service = 'defaults'
    sct_res = service_ctypes(service)\
        if not is_default else {'ctypes_stable': ['all'], 'success': True}
    if not sct_res['success']:
        return HttpResponseServerError(json.dumps(sct_res))
    is_meta = False if is_default else service in sct_res['serv_ct']['metaservices']
    if sct_res.get('ctypes_stable') or is_default:
        al_conf = get_alerts_conf(service, sct_res['ctypes_stable'][0] if sct_res.get('ctypes_stable') else '')
        if not al_conf['success']:
            return HttpResponseServerError(json.dumps(al_conf))
    else:
        al_conf = {'conf': {}}
    if is_default or not sct_res.get('ctypes_stable'):
        al_cmp = {'is_actual': True}
    else:
        al_cmpraw, err = dm_alerts.get_actuality(service, sct_res['ctypes_stable'][0])
        if err:
            al_cmp = {'is_actual': True, 'warning': err}
        else:
            al_cmp = json.loads(al_cmpraw)
    reformat_res = reformat_alerts_data(
        alerts['juggler'], alerts['golovan'], al_conf['conf'],
        sct_res.get('ctypes_stable', []), is_meta=is_meta)

    if request.GET.get('format', '') == 'json':
        return HttpResponse(json.dumps(reformat_res['juggler']))
    conf_keys = alert_keys_from_conf(al_conf['conf'], is_meta=is_meta)
    SIGS = SIGNALS()
    suggest_keys = [k for k in SIGS if k not in conf_keys]
    suggest_limits = {}
    for sk in suggest_keys:
        suggest_limits[sk] = al_conf['conf'].get('data', {}).get(sk, {}).get('limits', {})
        if not suggest_limits[sk]:
            suggest_limits[sk] = SIGS[sk].get('limits_example')
    return render_to_response('service_alerts.html',
                              {'data': reformat_res['juggler'],
                               'golovan_checks': reformat_res['golovan'],
                               'checks_conf': al_conf['conf'],
                               'resps': logins_from_conf(al_conf['conf'], False),
                               'resps_users': logins_from_conf(al_conf['conf'], True),
                               'notify_enable': should_have_juggler(al_conf['conf'], ''),
                               'actuality': al_cmp,
                               'is_default': is_default,
                               'sigkeys': suggest_keys,
                               'suggest_limits': suggest_limits,
                               'user': user,
                               'service': service})


def check_alerts(request):
    service = request.GET.get('service', '')
    ctype = request.GET.get('ctype', '')
    if not service or not ctype:
        return HttpResponseBadRequest('error: service or ctype not selected')
    if not ctype.startswith("stable"):
        return HttpResponse(json.dumps({"info": "ctype is not stable"}))

    ans, err = dm_alerts.get_actuality(service, ctype)
    if err:
        try:
            err = err['answer']
        except:
            pass
        return HttpResponseBadRequest(err)
    return HttpResponse(ans)


def status_alerts(request):
    serv, serv_ct, _, err = cluster_data.get_services()
    serv_pairs = []
    [serv_pairs.extend([[ct, srv, srv.replace('_', '_&shy')] for srv in servs]) for ct, servs in serv_ct.items() if ct.startswith('stable')]
#    serv_ct = dict([(ct, servs) for ct, servs in serv_ct.items() if ct.startswith('stable')])
    nsigs = len(serv_pairs)
    nlines = int(nsigs ** 0.5)
    serv_table = []
    for i in range(nlines+1):
        serv_table.append(serv_pairs[min(i*nlines, nsigs):min(nsigs, (i+1)*nlines)])
    return render_to_response('alerts_status.html', {'data': serv_table})


def alerts_cgi_parse(cgi):
    if 'warn' in cgi and 'crit' in cgi:
        return {'subject': 'limits',
                'fields': {'warn': float(cgi['warn']),
                           'crit': float(cgi['crit']),
                           'avgsec': int(cgi.get('avgsec') or 0)}}
    flap_fields = ['critical_time', 'stable_time', 'boost_time']
    if [f for f in flap_fields if f in cgi]:
        try:
            return {'subject': 'flaps',
                    'fields': dict([(ff, int(cgi.get(ff) or 0)) for ff in flap_fields])}
        except Exception as e:
            return {'subject': 'unknown',
                    'error': 'detected fields for flaps, but they are not integer, %s' % e}
    if 'phone_times' in cgi:
        pht = cgi['phone_times']
        if 'always' in pht or not pht.strip():
            fields = {}
        else:
            try:
                t_start, t_end = [t.strip() for t in pht.strip().split('-') if t.strip()]
                fields = {'time_start': t_start, 'time_end': t_end}
            except Exception as e:
                return {'subject': 'unknown', 'error': 'cannot parse phone times, %s' % e}
        return {'subject': 'phone_times', 'fields': fields}
    if 'disable_notify' in cgi:
        dis = cgi['disable_notify']
        if not dis or dis.lower() in ('0', 'false', 'no', 'off'):
            disable = 0
        else:
            disable = 1
        return {'subject': 'disable_notify', 'fields': disable}
    if 'user_group' in cgi:
        is_user = 1 if cgi.get('user_group', '') == 'user' else 0
        return {'subject': 'is_users', 'fields': is_user}
    else:
        return {'subject': 'unknown', 'error': 'no specific cgis found'}


def post_alerts(request):
    full_reset = request.GET.get('rewrite')
    add_alert = request.GET.get('add')
    do_juggler = request.GET.get('juggler')
    service = request.GET.get('service')
    service = 'defaults' if is_default_service(service) else service
    if not service:
        return HttpResponseBadRequest('service must be specified')
    login = request.yauser.login if request.yauser.is_authenticated() else 'unauthorized'
    if not is_saas_developer(login):
        return HttpResponseBadRequest(
            json.dumps({'success': False, 'error': 'login ' + login + ' is not saas developer'}))
    if full_reset:
        ctype = request.GET.get('ctype')
        ctypes = []
        sct_res = service_ctypes(service, ctype)
        if not sct_res['success']:
            return HttpResponseServerError(json.dumps(sct_res))
        if service and not sct_res['match_success']:
            return HttpResponseBadRequest(json.dumps({'error': sct_res['match_error']}))
        is_meta = service in sct_res['serv_ct']['metaservices']
        if ctype:
            ctypes = [ctype, ]
        else:
            ctypes = sct_res['ctypes_stable']
        res = {'results': []}
        for ctp in ctypes:
            send_1 = set_alert(service, ctp, do_juggler=do_juggler, is_meta=is_meta)
            res['results'].append(send_1)
            res['success'] = res.get('success', True) and send_1['success']
    elif add_alert:
        a_key = request.GET.get('skey')
        if not a_key:
            return HttpResponseBadRequest('not found skey cgi parameter')
        try:
            warn = float(request.GET['warn'])
            crit = float(request.GET['crit'])
            avgsec = int(request.GET.get('avgsec') or 0)
        except Exception as e:
            return HttpResponseBadRequest('cannot find float warn and crit params, error: %s' % e)

        is_users, is_sla_only = False, False
        try:
            is_users = request.GET.get('is_users')
            is_sla_only = request.GET.get('sla_only')
        except Exception as e:
            HttpResponseBadRequest('cannot parse is_users and sla params, error: %s' % e)

        do_add_default = request.GET.get('add_default')
        al_options = {'limits': {'warn': warn, 'crit': crit, 'avgsec': avgsec}}
        if is_users:
            al_options["is_users"] = 1
        res = patch_conf(service, a_key,
                         al_options,
                         do_add=do_add_default,
                         is_sla_only=is_sla_only,
                         login=login)
    else:
        df = alerts_cgi_parse(request.GET)
        if df['subject'] == 'unknown':
            return HttpResponseBadRequest(
                'cannot detect subject, error: %s' % df.get('error'))
        alert_key = request.GET.get('skey')
        res = change_alert(alert_key,
                           fields=df['fields'],
                           service=service,
                           subject=df['subject'],
                           login=login)
    if not res['success']:
        return HttpResponseServerError(json.dumps(res))
    return HttpResponse(json.dumps(res, indent=4))


def clear_alerts(request):
    dry_run = not request.GET.get('do')
    ans, err = dm_alerts.clear_left_alerts(dry_run)
    if err:
        try:
            err = json.loads(err['answer'])
        except:
            pass
        return HttpResponse(json.dumps({'success': False, 'answer': err}))
    return HttpResponse(ans)


def alerts_panel(request):
    alert_res = get_all_alerts_names()
    if not alert_res['success']:
        return HttpResponse(alert_res)
    filter = request.GET.get('filter', '')
    alert_res['alerts'] = [an for an in alert_res['alerts'] if filter in an]
    alerts_conf = [[{'alertname': name,
                     'lightname':  alert_service_from_name(name) + ' ' + filter,
                     'metagroup': 'ASEARCH'} for name in alert_res['alerts']]]
    return render_to_response('alerts_panel.html', {'data': alerts_conf,
                                                    'filter': filter})
