# -*- coding: utf-8 -*-
"""
Created on Jul 1, 2016

@author: noob
"""

from .layout import MonitoringControlsProcessor
from api.views.jobclose import JobClose
from common.models import Job, Server, Project, DeletedJob, LoadScheme
from common.views import get_common
from common.util.decorators import approve_required
from offlinepage.views.offlinepage import Metainfo
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.db import connections
from django.http import HttpResponseRedirect, HttpResponseBadRequest, HttpResponse, HttpRequest, \
    HttpResponseServerError
from django.shortcuts import render_to_response, render
from django.template import RequestContext
from hashlib import md5
from json import dumps
from monitoring.models import JobMetricTarget
import logging
from common.util.clients import ClickhouseClient


@login_required
def onlinepage(request, job):
    """

    :param request: HTTP request
    :param job: Job NUMBER
    """
    user = request.user
    common_data = get_common(request, user.id)
    try:
        job_obj = Job.objects.get(n=job)
    except ObjectDoesNotExist:
        return render_to_response('error.html',
                                  {'common': common_data, 'error': 'no_job'},
                                  RequestContext(request))
    if not job_obj.is_online:  # offline
        return HttpResponseRedirect('/%s' % job_obj.n)  # redirect to offline page

    owner = bool(user == job_obj.user)

    ch_client = ClickhouseClient()
    data_is_present = bool(ch_client.select('''
        select 
        any(job_id) as j 
        from loaddb.rt_microsecond_details_buffer
        where job_id=%(job)s 
        union all
        select
        any(job_id) as j 
        from loaddb.monitoring_verbose_data_buffer
        where job_id=%(job)s
        
    ''', query_params=job_obj.basic_query_params)[0][0])

    if not data_is_present:
        return render_to_response('error.html',
                                  {'common': common_data,
                                   'fire_id': job_obj.n,
                                   'error': 'no_data_in_trail',
                                   'owner': owner},
                                  RequestContext(request))

    try:
        loadscheme = job_obj.loadscheme_set.all()
        scheme = []
        if loadscheme:
            loadscheme = loadscheme.order_by('load_from')
            load_from = loadscheme[0].load_from
            load_to = loadscheme[loadscheme.count() - 1].load_to
            prev_dsc = ''
            for ls in loadscheme:
                if not prev_dsc or prev_dsc != ls.dsc:
                    scheme.append(ls.dsc)
                prev_dsc = ls.dsc
        else:
            load_from = 0
            load_to = 0
        scheme = ', '.join(scheme) if scheme else ''
        metainfo = Metainfo(job_obj)

        return render_to_response('onlinepage.html', {'user': user,
                                                      'common': common_data,
                                                      'job': job_obj,
                                                      'schema': scheme,
                                                      'load_from': load_from,
                                                      'load_to': load_to,
                                                      'net_errors': metainfo.net_errors,
                                                      'http_codes': metainfo.http_codes,
                                                      'user_avatar_link': metainfo.avatar_link,
                                                      'user_profile_link': metainfo.profile_link,
                                                      'multitag': job_obj.multitag,
                                                      'owner': owner,
                                                      }, RequestContext(request))
    except:
        logging.exception('Could not render onlinepage for job %s due to:', job)
        return render_to_response('error.html',
                                  {'common': common_data, 'error': 'no_job'},
                                  RequestContext(request))


@login_required
def refresh_meta_info(request):
    try:
        job = request.GET.get('job')
        assert job
        job_obj = Job.objects.get(n=job)
        metainfo = Metainfo(job_obj)
        return HttpResponse(dumps({'online': job_obj.is_online,
                                   'net_errors': metainfo.net_errors,
                                   'http_codes': metainfo.http_codes,
                                   }))
    except (ObjectDoesNotExist, AssertionError):
        return HttpResponseBadRequest('invalid job specified')
    except Exception:
        logging.exception('')
        return HttpResponseServerError('')


@login_required
def refresh_tags(request):
    try:
        job = request.GET.get('job')
        assert job
        job_obj = Job.objects.get(n=job)
        return HttpResponse(dumps([('', 'Overall')] + [(md5(tag.encode('utf-8')).hexdigest(), tag)
                                                       for tag in job_obj.tags]),
                            content_type='application/json')
    except (ObjectDoesNotExist, AssertionError):
        return HttpResponseBadRequest('invalid job specified')
    except Exception:
        logging.exception('')
        return HttpResponseServerError('')


@login_required
def refresh_monitoring_controls(request):
    try:
        job = request.GET.get('job')
        assert job
        job_obj = Job.objects.get(n=job)
        controls = MonitoringControlsProcessor(job_obj)
        return HttpResponse(dumps({'targets': controls.targets,
                                   'metrics': controls.metrics_groups}), content_type='application/json')
    except (ObjectDoesNotExist, AssertionError):
        return HttpResponseBadRequest('invalid job specified')
    except Exception:
        logging.exception('')
        return HttpResponseServerError('')


@login_required
def render_custom_report_form(request):
    try:
        job = request.GET.get('job')
        assert job
        job_obj = Job.objects.get(n=job)
        custom_metrics = [jmt.metric
                          for jmt in JobMetricTarget(job_obj.n, bypass_cache=True).objects
                          if jmt.metric.startswith('custom:')]
        custom_metrics_single = set([metric.split(":")[1]
                                     for metric in custom_metrics
                                     if [m.split(":")[1].split('_')[0]
                                         for m in custom_metrics].count(metric.split(":")[1].split('_')[0]) == 1])
        custom_metrics_groups = set([metric.split(":")[1].split('_')[0]
                                     for metric in custom_metrics
                                     if [m.split(":")[1].split('_')[0]
                                         for m in custom_metrics].count(metric.split(":")[1].split('_')[0]) > 1])

        return render(request, 'custom_report_form.html', {
            'job': job_obj.n,
            'custom_metrics_single': custom_metrics_single,
            'custom_metrics_groups': custom_metrics_groups,
            'targets': job_obj.targets,
        })
    except (ObjectDoesNotExist, AssertionError):
        return HttpResponseBadRequest('invalid job specified')


@login_required
@approve_required
def job_edit(request, job):
    """

    :param request: HTTP request
    :param job: Job NUMBER
    """
    user = request.user
    common = get_common(request, user.id)

    try:
        job_obj = Job.objects.get(n=job)
    except ObjectDoesNotExist:
        return render_to_response('error.html',
                                  {'common': common, 'error': 'no_job'},
                                  RequestContext(request))

    if request.method == 'GET':

        projects = Project.objects.filter(owner=user.username)

        return render_to_response('edit.html',
                                  {'common': common,
                                   'user': user,
                                   'job': job_obj,
                                   'projects': projects,
                                   },
                                  RequestContext(request))
    elif request.method == 'POST':
        logging.debug('JOB %s EDIT POST %s', job, request.POST)
        try:
            job_obj.ver = request.POST.get('ver_new')
            job_obj.name = request.POST.get('name_new')
            job_obj.dsc = request.POST.get('dsc_new')
            job_obj.srv_port = request.POST.get('port_new')
            job_obj.instances = request.POST.get('instances_new')
            try:
                srv_new = Server.objects.get(n=request.POST.get('srv_new'))
                job_obj.srv = srv_new
            except ObjectDoesNotExist:
                logging.exception('No such Server %s: \n', request.POST.get('srv_new'))
            job_obj.save()
            logging.info('Successfully updated job %s', job)

        except:
            logging.exception('Could not submit job %s editing, due to:', job)

        return HttpResponseRedirect('/%s' % job_obj.n)


@login_required
@approve_required
def addtofav(request):
    job_n = request.POST.get('job_id')
    try:
        assert job_n
        job_obj = Job.objects.get(n=job_n)
    except (AssertionError, ObjectDoesNotExist, ValueError):
        return HttpResponseBadRequest('Invalid job')
    job_obj.flag = 0 if job_obj.flag else 1
    job_obj.save()
    return HttpResponse(dumps({'status': 1, 'error': ''}), content_type='application/json')


@login_required
@approve_required
def deletejob(request):
    job_n = request.POST.get('job_id', 0)
    job = Job.objects.filter(n=job_n)
    if not job:
        return HttpResponse(dumps({'status': 0, 'error': 'There is no such job!'}), content_type='application/json')
    _delete_job(job[0], user=request.user.username)
    return HttpResponse(dumps({'status': 1, 'error': ''}), content_type='application/json')


def _delete_job(job, user='overload'):
    """

    :param job: Job OBJECT
    """
    try:
        if not job.td:  # close online job before deleting;
            request = HttpRequest()
            request.method = 'get'
            user_overload = User.objects.get(username=user)
            request.user = user_overload
            riper = JobClose()
            riper.get(request, job)

        d = DeletedJob(n=job.n,
                       up=job.up,
                       fd=job.fd,
                       td=job.td,
                       user=job.user,
                       name=job.name,
                       dsc=job.dsc,
                       type=job.type,
                       tank=job.tank,
                       command_line=job.command_line,
                       ammo_path=job.ammo_path,
                       loop_cnt=job.loop_cnt,
                       quit_status=job.quit_status,
                       test_type=job.test_type,
                       srv=job.srv,
                       srv_port=job.srv_port,
                       instances=job.instances,
                       flag=job.flag,
                       component=job.component,
                       ver=job.ver,
                       configinfo=job.configinfo,
                       finalized=job.finalized)
        d.save()

        cursor = connections['default'].cursor()
        sql = '''
                delete from regression_comment where job_id=%(job)s;
                delete from monitoring_jobmetrictarget where job_id=%(job)s;
                '''
        cursor.execute(sql, {'job': job.n})
        cursor.close()

        LoadScheme.objects.filter(up=job).delete()

        job.delete()

        return 1
    except:
        logging.exception('')
        return 0
