import requests
import json
import pandas as pd
import time
from scripts.constants.tag_constants import prev_tag_data
from scripts.config.json_reader import tags_list, application_config
from scripts.util.logger import logger


class kairos_utils(object):
    def __init__(self):
        self.data_arr = []
        self.totaliser_tag = tags_list

        self.kairos_url = application_config['kairos']['reader_url']

    @staticmethod
    def create_query_max_one_min(start_time, end_time, tag_list):

        query = {
            "metrics": [
                {
                    "tags": {
                        "c3": tag_list
                    },
                    "name": "ilens.live_data.raw",
                    "group_by": [
                        {
                            "name": "tag",
                            "tags": [
                                "c3"
                            ]
                        }
                    ],
                    "aggregators": [
                        {
                            "name": "max",
                            "sampling": {
                                "value": "1",
                                "unit": "minutes"
                            },
                            "align_start_time": True
                        }
                    ]
                }
            ],
            "plugins": [],
            "cache_time": 0,
            "start_absolute": start_time,
            "end_absolute": end_time
        }
        return query

    def fetch_datapoints_from_kairos(self, query):
        response = requests.post(self.kairos_url, json=query, timeout=600)
        status_code = response.status_code
        logger.info(f"Received status code {status_code} from kairos")
        if status_code in [200, 204]:
            return response.json()
        else:
            return dict()

    @staticmethod
    def create_kairos_df(response_data):
        """
        Definition for creating kairos DataFrame
        """
        master_df = pd.DataFrame(columns=["timestamp"])

        for each_response in response_data["queries"]:
            if each_response["sample_size"] == 0:
                continue
            for each_result in each_response["results"]:
                if not each_result["tags"]:
                    selected_hierarchy = each_result["group_by"][0]["group"]["c3"]
                    df = pd.DataFrame(columns=["timestamp", "value"])
                    new_column_name = selected_hierarchy
                    df.rename(columns={"value": new_column_name}, inplace=True)
                    master_df = master_df.merge(
                        df, on='timestamp', how='outer')
                    continue
                kairos_data = each_result["values"]
                selected_hierarchy = each_result["group_by"][0]["group"]["c3"]
                df = pd.DataFrame(kairos_data, columns=["timestamp", "value"])
                new_column_name = selected_hierarchy
                df.rename(columns={"value": new_column_name}, inplace=True)
                master_df = master_df.merge(df, on='timestamp', how='outer')

        master_df.set_index("timestamp", inplace=True)
        master_df.sort_index(inplace=True)
        return master_df

    def write_template(self, tag_id, value, timestamp):
        temp_json = {
            "name": "ilens.live_data.raw",
            "datapoints": [[int(timestamp), value]],
            "tags": {
                "c3": self.totaliser_tag[tag_id],
                "c1": self.totaliser_tag[tag_id].split("$")[0],
                "c5": self.totaliser_tag[tag_id].split("$")[-1]
            }
        }
        self.data_arr.append(temp_json)

    def kairos_write(self):
        response = requests.post("http://192.168.0.217:8080/api/v1/datapoints",
                                 data=json.dumps(self.data_arr),
                                 headers={'content-type': 'application/json'})
        self.data_arr = []
        logger.info("Pushed raw data to KairosDB with status code:" +
                    str(response.status_code))


def totalizer_calculator():
    logger.info('KAIROS')
    kairos_obj = kairos_utils()

    start_time = int(1609459200) * 1000
    end_time = int(time.time()) * 1000

    for tag in tags_list:
        logger.info(f'TAG : {tag}')
        query = kairos_obj.create_query_max_one_min(start_time, end_time, tag)
        data = kairos_obj.fetch_datapoints_from_kairos(query)
        data_frame = kairos_obj.create_kairos_df(data)
        data_frame.dropna(inplace=True)
        data_frame.reset_index(inplace=True)
        vals = data_frame.to_dict(orient='records')
        prev_totaliser_value = 0
        for index in range(len(vals)):
            if index == 0:
                timestamp = int(vals[index]['timestamp'])
                totalised_value = vals[index][tag]
            else:
                current_time = int(vals[index]['timestamp'])
                current_value = vals[index][tag]
                time_diff = (((current_time - prev_time) / 1000) / 60)
                if time_diff <= 60:
                    totalised_value = (time_diff / 60) * \
                                      ((prev_value + current_value) / 2)
                else:
                    totalised_value = (time_diff / 60) * \
                                      ((0 + current_value) / 2)

                timestamp = current_time

                # TODO: TIME BASED LOGIC TO SET prev_totaliser_value = 0
                start = time.strptime(time.strftime(
                    '%Y-%m-%d %H:%M:%S', time.localtime(prev_time / 1000)), '%Y-%m-%d %H:%M:%S')
                end = time.strptime(time.strftime(
                    '%Y-%m-%d %H:%M:%S', time.localtime(current_time / 1000)), '%Y-%m-%d %H:%M:%S')
                start_day = start.tm_mday
                end_day = end.tm_mday
                if start_day != end_day:
                    prev_totaliser_value = 0
                else:
                    pass
            if totalised_value < 0:
                totalised_value = 0
            prev_totaliser_value += totalised_value
            prev_time = int(vals[index]['timestamp'])
            prev_value = vals[index][tag]

            kairos_obj.write_template(tag_id=tag,
                                      value=prev_totaliser_value,
                                      timestamp=timestamp)

            prev_tag_data[tag] = {
                'previous_value': prev_value,
                'previous_time': prev_time,
                'previous_totalized_value': prev_totaliser_value
            }
        kairos_obj.kairos_write()
    logger.info(f'tags_data_after_kairos : {prev_tag_data}')
    return True
