from django.conf import settings
from django.core.management import BaseCommand

#!/usr/bin/env python
#from db_manager import get_rules
import os
import sys

project_dir=os.path.abspath("../../../")
sys.path.append(project_dir)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "alert_rule_engine.settings")
import json

from backend import query_alerts, query_custom_alerts, view_obj
import time
from common.logger import log
from alert_rule_enginelib.utils import nowtime_offset, utc2sin
from alert_rule_enginelib.models import *
from alert_rule_enginelib.db_manager import *
import requests

import click

class AlertMessage():

    def __init__(self, task):
        self.task = task
        self.rule_id = task.rule_id
        self.conditions = task.rule.conditions
        self.message = json.loads(task.message)
        self.message_body = ""
        self.rst_status = []
        self.alert = None
        self.aggevents = {}
        self.sorted_alerts = {}

    def test():
        pass

    def sort_events(self, alert, is_recovered=False):
        index = alert['host']
        sorted_alerts = {
                'conditions': self.conditions,
                'need_action': [],
                'recovered': []
                }
        if not(self.aggevents.get(index)):
            self.aggevents[index] = []

        if  index == alert['host']:
            alert_items=utc2sin(alert['time'])[1], alert['value'], alert['message']
            print alert_items
            self.aggevents[index].append(alert_items)

        # reformat alerts here
        for k,v in self.aggevents.items():
            if v[0][1] == 0:
                status="RECOVERED"
            elif v[0][1] == 1:
                status = "NEED ACTION"
            else:
                status = "UNKNOWN"

            # not going to get config from gims, it takes huge mount of time!!!
            # for the workaround method, the host info will be generated by the
            # template  see --> generate_lines() below
            #host_name = get_host_from_gims(k)

            if status != "RECOVERED":
                sorted_alerts['need_action'].append([k, v[0][0], v[0][2], status])
                #sorted_alerts['need_action'].append([k, host_name, v[0][0], status])
            elif status == 'RECOVERED':
                sorted_alerts['recovered'].append([k, v[0][0], v[0][2], status])
                #sorted_alerts['recovered'].append([k, host_name, v[0][0], status])
            else:
                pass

        return sorted_alerts

    def _send_alert(self, msg, group=None, test=False):
        url = "https://mattermost.garenanow.com/hooks/c3z4dyran7ny5e3kdi3gx9rujr"
        payload = {
                "channel": "shopee-alarm-others",
                "username": "NotiBot",
                "text": msg
                }
        if test:
            sys.exit()
        if msg is None:
            print "ERROR no message founc, {0}".format(msg)
        res = requests.post(url, data=json.dumps(payload))
        if res.ok:
            log.info("{0} | send ok".format(msg))
        else:
            log.error("{0} | {1} send failed".format(msg, res.content))
        return res


    def run(self, group=None, msg=None, test=False):
        for action, _message in self.message.items():
                for alert in _message:
                    if action == u'send_alone':
                        #print action
                        self.alert = self.format_message(alone_message=alert, message_type='send_alone')
                        print "{0}".format(self.alert)
                        if test:
                            self.rst_status = []
                        else:
                            #print self.alert
                            if self.alert is not None:

                                returntrue = self._send_alert(msg=self.alert).ok
                                self.rst_status.append(returntrue)
                            else:
                                self.rst_status.append(self.alert)
                    elif action == 'aggregated':
                        #self.alert = self.format_message(alert, 'aggregated')
                        self.sorted_alerts = self.sort_events(alert)
                        self.alert = self.sorted_alerts
                    else:
                        pass
                #print action
                if action == 'aggregated':
                    self.alert = self.format_message(message_type='aggregated')
                    #print "message_body {0}".format(self.message_body)
                    if self.alert is not None:
                        if test:
                            self.rst_status = []
                        else:
                            returntrue = self._send_alert(msg=self.alert).ok
                            self.rst_status.append(returntrue)
                    else:
                        self.rst_status.append(self.alert)

        return self.rst_status


    def format_message(self, alone_message=None, message_type=None, detailed=False):
        if self.message_body is not None:
            # format to send alone
            if message_type == 'send_alone':
                self.message_body = self._format_send_alone(alone_message=alone_message)
            # format to aggregated
            if message_type == 'aggregated':
                self.message_body = self._format_aggregated(self.sorted_alerts, detailed=False, enable_recovered=True)
            return self.message_body
        else:
            return None

    def _format_send_alone(self, alone_message=None, detailed=True):
        self.message_body = ""
        if alone_message['value'] == 1:
            status = "NEED ACTION"
        elif alone_message['value'] == 0:
            status = 'RECOVERED'
        else:
            status = 'UNKNOWN'
        # get metadata by hostname from GIMS
        host_name = get_host_from_gims(alone_message['host'])

        self.message_body += '''Rule Engine | {0} | {1}| {2} | due to : {3} | serverity: {4}|detailed info: {5}, ({9})| up_depends: {6} next_trigger: {7} |status: {8}\n'''.format(self.conditions,
                utc2sin(alone_message["time"])[1],
                #alone_message["region"], alone_message["agent"], alone_message["application"], alone_message["service"], alone_message['host'],
                alone_message['host'],
                alone_message['service'],
                "Critical",
                alone_message["message"],
                self.task.rule.depends, self.task.rule.next_trigger,
                status,
                host_name
                )
        return self.message_body


    def _format_aggregated(self, sorted_alerts, detailed=True, md_table=False, enable_recovered=False):
        if not self.aggevents:
            return None

        if not sorted_alerts:
            return None

        self.message_body="#### Rule Engine| AGGREGATION ALERT | Matched: {0}####\n\n".format(self.conditions)
        self.msg_warn("#### Rule Engine | AGGREGATION ALERT | Matched: {0} \n".format(self.conditions))
        title_need_action= "---\n ##### NEED ACTION | Overview\n\n"
        body_need_action =""
        title_recovered = "\n---\n\nRECOVERED | Overview\n\n"
        body_recovered=""
        md_table_title='''|host | time | host_info| status |
        | :------------ |:----:|:----:| -----:|\
                '''

        for k,v in sorted_alerts.items():
            # generate_lines separated by | and \n
            if k == 'need_action':
                if v:
                    body_need_action += "\n".join([generate_lines(i, note=True) for i in v ])
                    if md_table:
                        self.message_body += (title_need_action + md_table_title + body_need_action + "\n")
                    else:
                        self.message_body += (title_need_action + body_need_action + "\n")
                    self.msg_danger(body_need_action)

            if k == 'recovered':
                if enable_recovered and v:
                    body_recovered += "\n".join([generate_lines(i) for i in v ])
                    if md_table:
                        self.message_body += (title_recovered + md_table_title + body_recovered + "\n")
                    else:
                        self.message_body += (title_recovered + body_recovered + "\n")
                    self.msg_ok(title_recovered + body_recovered)

        return self.message_body


    def msg_ok(self, msg):
        return click.secho(msg, fg='green')

    def msg_warn(self, msg):
        return click.secho(msg, fg='yellow')

    def msg_danger(self, msg):
        return click.secho(msg, fg='red')

    def html(self, message_body):
        pass

    def json(self, message_body):
        pass

    def text(self, message_type):
        pass

    def update_status(self, rst_status):
        if rst_status:
            if False not in rst_status:
                # if no error in return code, make task as '0' - Done
                self.task.status = 0
                self.task.save()


def get_config_from_gims(host='all', project="shopee"):
    headers = {
            'Authorization': "Bearer ab1eca73e8f0b90a6d81d777afb51e2887b88e0e8fcb990b22514d5629516c7a",
            'content-type': 'application/json'
            }
    if host != 'all':
        url = "http://gims.garenanow.com/api/servers?iplan={0}&project={1}".format(host, project)
    else:
        url = "http://gims.garenanow.com/api/servers?project={0}".format(project)
    try:
        rst = requests.get(url, headers=headers, timeout=2)
    except Exception as e:
        print ("get not get config from gims for {0}| {1}".format(host, e))
        log.error("get not get config from gims for {0}".format(host))
        return None

    if rst.ok:
        return rst.json()
    else:
        return None


def get_config_from_gims_all(host):
    headers = {
            'Authorization': "Bearer ab1eca73e8f0b90a6d81d777afb51e2887b88e0e8fcb990b22514d5629516c7a",
            'content-type': 'application/json'
            }
    url = "http://gims.garenanow.com/api/servers?iplan={0}".format(host)
    try:
        rst = requests.get(url, headers=headers, timeout=1)
    except Exception as e:
        print ("get not get config from gims for {0}| {1}".format(host, e))
        log.error("get not get config from gims for {0}".format(host))
        return None

    if rst.ok:
        return rst.json()
    else:
        return None


def get_host_from_gims(host):
    if host:
        rst = get_config_from_gims_all(host)
        if rst is None or (len(rst) > 1 or len(rst)) == 0:
            host_name = "no matched from gims"
        else:
            host_name = rst[0]['name']
    else:
        return None
    return host_name


def generate_lines(sorted_list, note=False, **kwargs):
    """ receives list , and returns a line or None Type"""
    if isinstance(sorted_list, list):
        line="|".join([str(i) for i in sorted_list])
        host_name = get_host_from_gims(sorted_list[0])
        print line
        if note:
            line = "-> " + line + "  ({0})".format(host_name)
        return line
    else:
        return None


class Command(BaseCommand):
    from optparse import make_option

    option_list = BaseCommand.option_list + (
            make_option("-d","--detail",action="store_true",dest="detail",default=False),
            make_option("-t","--test",action="store_true",dest="test",default=False),
            )

    def handle(self, *args, **options):
        start = time.time()
        tasks = get_active_tasks()
        type(tasks)
        for task in tasks:
            #print "Task before input task_id: {0}, {1}, message: {2}".format(task.task_id, task.rule.conditions, task.message)
            print "Task before input task_id: {0}, {1}".format(task.task_id, task.rule.conditions)
            log.info("Task before input task_id: {0}, {1}".format(task.task_id, task.rule.conditions))
            alert_message = AlertMessage(task)
            rst_status=alert_message.run(test=options['test'])
            #print options['test']
            print task.rule.conditions, rst_status
            if not options['test']:
                alert_message.update_status(rst_status)


if __name__ == '__main__':
    #tasks = get_active_tasks()
    #for task in tasks:
    #    alert_message = AlertMessage(task)
    #    rst_status = alert_message.run()
    #    if False not in rst_status:
    #        task.status = 0
    #        task.save()
    #conf = get_config_from_gims_all(host='10.0.1.72')
    conf = get_config_from_gims(host='all')
    #print conf[0]
    print conf
    print len(conf)

    #t77 = get_task(5)
    #print t77.rule_id, t77.message
    #alert_message = AlertMessage(t77)
    #alert_message.run()
    #print alert_message.aggevents
    #alert_message.send_aggreated()
