# -*- coding: utf-8 -*-

import datetime
import logging
import re

import saas.tools.ssm.modules.startrek_api as startrek_api

from saas.library.python.deploy_manager_api import SaasService
from saas.library.python.sandbox.api import SandboxApi
from saas.library.python.token_store import PersistentTokenStore
from saas.library.python.token_store.errors import PersistentTokenStoreError


sandbox_token = ''
try:
    sandbox_token = PersistentTokenStore.get_token_from_store_env_or_file('sandbox')
    sandbox_api = SandboxApi(oauth_token=sandbox_token)
except PersistentTokenStoreError:
    logging.warning('Attention! ENV variable with auth token was not found!')

startrek_client = startrek_api.SaaSStartrekWorkflow(queue='SAASLOADTEST')


def shoot_to_saas_service(form):
    params = {key: form.data[key] for key in form.data if key not in ['csrf_token', 'submit', 'user_login']}
    params['locations'] = [str(el).lower() for el in params['locations'].replace(' ', '').split(',')]
    logging.info(params)
    task = sandbox_api.add_task('SHOOT_TO_SAAS_SERVICE', task_owner='SAAS-ROBOT', task_params=params)
    logging.info(str(task))
    task.start()
    return 'Стрельба успешно запущена: <a href=https://sandbox.yandex-team.ru/task/{}>{}</a>'.format(task.id, task.id)


def load_table():
    schedulers = []
    tasks = []
    rps = []

    for scheduler in sandbox_api.find_schedulers(task_type='SHOOT_TO_SAAS_SERVICE', full_info=True):
        try:
            scheduler_form, task, target_rps = prepare_scheduler_info_for_table(scheduler)

            schedulers.append(scheduler_form)
            tasks.append(task)
            rps.append(target_rps)
        except KeyError as e:
            logging.warning('An error occurred: %s %s, scheduler %d is probably incorrect', type(e), e, scheduler.id)
        except TypeError as e:
            logging.exception(e, exc_info=True)

    return schedulers, tasks, rps


def prepare_scheduler_info_for_table(scheduler):
    last_task = scheduler.last_task.dict() if scheduler.last_task else None

    scheduler = scheduler.dict()
    scheduler_form = scheduler2form(scheduler)

    if scheduler_form['target_rps']:
        target_rps = scheduler_form['target_rps']
    else:
        saas_service = SaasService(scheduler_form['ctype'], scheduler_form['service'])
        basic_locations_num = len(set(saas_service.locations).intersection({'MAN', 'SAS', 'VLA'}))
        target_rps = int(saas_service.sla_info['search_rps']) / (
            1 if basic_locations_num == 1 else (basic_locations_num - 1))

    return scheduler_form, last_task, target_rps


def load_form(request_id):
    if not request_id or request_id == 'new':
        return {}

    scheduler_id = request_id
    sandbox_scheduler = sandbox_api.scheduler_by_id(scheduler_id)
    return scheduler2form(sandbox_scheduler.dict()) if sandbox_scheduler else None


def form2scheduler(form_data):
    dtm_offset = datetime.datetime.now() - datetime.datetime.utcnow()
    notify_time = datetime.timedelta(hours=form_data['notify_time'])

    scheduler = form_data.copy()
    scheduler['start_time'] = scheduler['start_time'] - dtm_offset

    # notify_time is considered in the sandbox task, we wait there
    scheduler['start_time'] = (scheduler['start_time'] - notify_time).isoformat()

    scheduler['repetition'] = {
        'interval': scheduler['repetition_interval'] * 3600
    }

    task_params = form_data.copy()
    task_params['locations'] = form_data['locations'].replace(' ', '').split(',')
    task_params['responsibles'] = form_data['responsibles'].replace(' ', '').split(',')
    task_params['notify_time'] = form_data['notify_time'] * 3600
    task_params['target_rps'] = form_data['target_rps']
    task_params['start_time'] = scheduler['start_time']

    return scheduler, task_params


def scheduler2form(scheduler):
    params = {
        'scheduler_id': scheduler['id'],
        'owner': scheduler['owner'],
        'description': scheduler['task']['description'],
        'sequential_run': scheduler['schedule']['sequential_run'],
        'start_time': scheduler['schedule']['start_time'],
        'retry': scheduler['schedule']['retry'],
        'priority': scheduler['task']['priority'],
        'status': scheduler['status'] == 'STOPPED',
        'next_time': (str_to_datetime(scheduler['time']['next'])+(datetime.datetime.now()-datetime.datetime.utcnow())),
        'repetition_interval': scheduler['schedule']['repetition']['interval'] / 3600
    }
    params.update({el['name']: el['value'] for el in scheduler['task']['custom_fields']})
    params['responsibles'] = ', '.join(params['responsibles'])
    params['locations'] = ', '.join(params['locations'])
    params['notify_time'] = params['notify_time'] / 3600

    params['next_time'] = (
        params['next_time']
        + datetime.timedelta(hours=params['notify_time'])
        + datetime.timedelta(minutes=1)
    ).strftime('%Y-%m-%d %H:%M')

    params['start_time'] = (
        str_to_datetime(params['start_time'])
        + (datetime.datetime.now() - datetime.datetime.utcnow())
        + datetime.timedelta(hours=params['notify_time']) +
        datetime.timedelta(minutes=1)
    )
    return params


def str_to_datetime(date_str):
    if '.' in date_str:
        dt, us = date_str.split('.')
        us = int(us.rstrip('Z'), 10)
    else:
        dt, us = date_str.strip('Z'), 0
    dt = datetime.datetime.strptime(dt, '%Y-%m-%dT%H:%M:%S')
    return dt + datetime.timedelta(microseconds=us)


def schedule(form):
    if not form.scheduler_id.data:
        return create_new_scheduler(form)
    else:
        return modify_existing_scheduler(form)


def close_issue(issue):
    startrek_client.close_issue(issue)


def modify_existing_scheduler(form):
    scheduler_params, task_params = form2scheduler(form.data)
    sandbox_api.update_scheduler(
        scheduler_id=form.scheduler_id.data,
        scheduler_params=scheduler_params,
        task_params=task_params,
    )

    scheduler_id = form.scheduler_id.data
    scheduler = sandbox_api.scheduler_by_id(scheduler_id)

    if scheduler_params['status']:
        scheduler.stop()
    else:
        scheduler.start()

    startrek_client.add_to_followers(task_params['ticket'], task_params['responsibles'], add=False)

    return 'Шедулер <strong><a href=https://sandbox.yandex-team.ru/' \
           'scheduler/{}>{}</a></strong> успешно изменен'.format(form.scheduler_id.data, form.scheduler_id.data)


def create_new_scheduler(form):
    scheduler_params, task_params = form2scheduler(form.data)

    if not task_params['ticket']:
        service, ctype = task_params['service'], task_params['ctype']

        description = 'This ticket is about shooting to saas service {} in ctype {}'.format(service, ctype)
        summary = 'MAIN ticket of shooting to saas service {} in ctype {}'.format(service, ctype)
        ticket = startrek_client.create_issue(
            subject=summary,
            body=description,
            assignee='bvdvlg',
            tags=['mass_shooting'],
            followers=task_params['responsibles'],
        )
        task_params['ticket'] = str(ticket.json()['key'])

    if scheduler_params.get('owner') is not None:
        del scheduler_params['owner']

    scheduler = sandbox_api.add_scheduler(
        'SHOOT_TO_SAAS_SERVICE',
        owner='SAAS-ROBOT',
        scheduler_params=scheduler_params,
        task_params=task_params,
    )

    if scheduler_params['status']:
        scheduler.stop()
    else:
        scheduler.start()

    return 'Шедулер <a href=https://sandbox.yandex-team.ru/' \
           'scheduler/{}>{}</a> успешно создан'.format(scheduler.id, scheduler.id)


def name_value_search(lst, name):
    for el in lst:
        if el['name'] == name:
            return el['value']
    return None


def get_macro_from_html(string, func_name):
    func_macro = string[re.search(r'{{% *macro {}\(\w*\) *%}}'.format(func_name), string).end(0):]
    func_macro = func_macro[:re.search(r'{% *endmacro *%}', func_macro).start(0)]
    return func_macro
