from saas.library.python.token_store import TokenStore
from saas.library.python.sandbox.api import SandboxApi
import time
import requests


class ITSManager:
    _BASE_URL = 'https://ext.its.yandex-team.ru/v2/l7/heavy'
    _OAUTH_SLUG = 'nanny'

    def __init__(self):
        self.oauth_token = TokenStore.get_token_from_store_or_env(self._OAUTH_SLUG)
        self.headers = {'Authorization': 'OAuth {}'.format(self.oauth_token)}
        self.session = requests.Session()

    def make_request(self, method, action, headers=None, params=None, json=None):
        headers_list = {}
        if self.headers is not None:
            headers_list.update(self.headers)
        if headers is not None:
            headers_list.update(headers)
        response = self.session.request(method, "{}/{}".format(self._BASE_URL, action), headers=headers_list, params=params, json=json)
        return response

    def commit_its_config(self, namespace_id, task_owner="bvdvlg", by_balancer=None, common=None, **kwargs):
        sandbox_token = TokenStore.get_token_from_store_or_env('sandbox')
        sd_api = SandboxApi(oauth_token=sandbox_token)
        task_params = {"namespace_id": namespace_id, "by_balancer": ["service_balancer_off"], "common": ["cplb_balancer_load_switch"], "dont_off_balancers_by_marty": False}
        task_params.update(kwargs)
        task = sd_api.add_task(task_type="COMMIT_TO_ARCADIA_ITS", task_owner=task_owner, task_params=task_params)
        return task.start()

    def create_its_config(self, headers=None, params=None, **kwargs):
        create_its_request = {
            "group_id": "common",
            "its_value_path": "balancer/{}/common/common/cplb_balancer_load_switch".format(kwargs["id"].replace(".", "_")),
            "managers": {'groups': ['29441', '26994'], 'logins': ['coffeeman', 'bvdvlg']},
        }
        create_its_request.update(kwargs)
        response = self.make_request("post", "", headers=headers, params=params, json=create_its_request)
        print("Its l7 heavy config was created, to apply all changes you need to push them manually "
              "on https://nanny.yandex-team.ru/ui/#/{}/".format(kwargs['id']))
        return response

    def wait_its_config(self, namespace_id, max_retries=40, sleep_time=20):
        retries = 0
        while True:
            retries += 1
            if retries == max_retries:
                return 1
            try:
                self.sections_list(namespace_id).json()
                return 0
            except KeyError:
                time.sleep(sleep_time)

    def create_section(self, namespace_id, section_id, headers=None, params=None, **kwargs):
        if headers is None:
            headers = {}
        create_section_request = {
            "id": section_id,
            "managers": {'groups': ['29441', '26994'], 'logins': ['coffeeman', 'bvdvlg']},
            "locations": [{"id": "MAN"}, {"id": "SAS"}, {"id": "VLA"}],
            "exclude_from_bulk_actions": False
        }
        create_section_request.update(kwargs)
        headers['If-Match'] = self.current_sections_etag(namespace_id)
        response = self.make_request("post", "{}/weights/sections/".format(namespace_id), headers=headers, params=params, json=create_section_request)
        return response

    def sections_list(self, namespace_id, headers=None, params=None, **kwargs):
        return self.make_request("get", "{}/weights/sections/".format(namespace_id), headers=headers, params=params).json()

    def sections_weights(self, namespace_id, headers=None, params=None, **kwargs):
        return self.make_request('get', '{}/weights/values/'.format(namespace_id), headers=headers, params=params).json()

    def current_its_weights(self, namespace_id, headers=None, params=None):
        return self.make_request("get", '{}/weights/its_value/'.format(namespace_id), headers=headers, params=params).json()

    def current_sections_etag(self, namespace_id):
        current_sections = self.make_request("get", "{}/weights/sections/".format(namespace_id))
        return current_sections.headers['ETag']

    def push(self, namespace_id):
        current = self.current_its_weights(namespace_id)['current_version']
        target = self.current_sections_etag(namespace_id).strip('"')
        response = self.make_request('post', '{}/weights/its_value/'.format(namespace_id), json={
            'current_version': current,
            'target_version': target,
        })
        return response

    def set_weights(self, namespace_id, config, headers=None, params=None, **kwargs):
        if headers is None:
            headers = {}
        current_etag = self.current_sections_etag(namespace_id)
        headers['If-Match'] = current_etag
        response = self.make_request("post", '{}/weights/values/'.format(namespace_id), json=config, headers=headers, params=params)
        return response

    def delete_section(self, namespace_id, section_id, headers=None, params=None):
        if headers is None:
            headers = {}
        headers['If-Match'] = self.current_sections_etag(namespace_id).strip('"')
        response = self.make_request("delete", '{}/weights/sections/{}/'.format(namespace_id, section_id), headers=headers)
        return response
