#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import os
import re
import requests
import sys

QLOUD_HOST = 'https://qloud-ext.yandex-team.ru'
QLOUD_API_OAUTH_TOKEN = os.environ.get('QLOUD_API_OAUTH_TOKEN')


def get_dump(environment_id):
    path = '/api/v1/environment/dump/'
    url = '{host}{path}{env}'.format(host=QLOUD_HOST, path=path, env=environment_id)
    headers={
        'Authorization': 'OAuth %s' % QLOUD_API_OAUTH_TOKEN,
    }
    response = requests.get(url=url, headers=headers)
    response.raise_for_status()
    return response.json()


def get_current(environment_id):
    path = '/api/v1/environment/current/'
    url = '{host}{path}{env}'.format(host=QLOUD_HOST, path=path, env=environment_id)
    headers={
        'Authorization': 'OAuth %s' % QLOUD_API_OAUTH_TOKEN,
    }
    response = requests.get(url=url, headers=headers)
    response.raise_for_status()
    return response.json()


def upload(dump):
    path = '/api/v1/environment/upload/return-header?targetState=DEPLOYED&skipIfNoChange=false'
    url = '{host}{path}'.format(host=QLOUD_HOST, path=path)
    headers={
        'Authorization': 'OAuth %s' % QLOUD_API_OAUTH_TOKEN,
    }
    response = requests.post(url=url, headers=headers, json=dump)
    response.raise_for_status()
    return response.json()


def drop(environment_id):
    path = '/api/v1/environment/stable/'
    url = '{host}{path}{env}'.format(host=QLOUD_HOST, path=path, env=environment_id)
    headers={
        'Authorization': 'OAuth %s' % QLOUD_API_OAUTH_TOKEN,
    }
    response = requests.delete(url=url, headers=headers)
    response.raise_for_status()
    return response.text


def create_domain(environment_id, domain_data):
    path = '/api/v1/environment-domain/'
    url = '{host}{path}{env}'.format(host=QLOUD_HOST, path=path, env=environment_id)
    headers={
        'Authorization': 'OAuth %s' % QLOUD_API_OAUTH_TOKEN,
    }
    response = requests.put(url=url, headers=headers, json=domain_data)
    response.raise_for_status()
    return response.json()


def get_instance_groups(units):
    return [{
        'location': 'ALL',
        'units': units,
        'backup': False,
        'weight': 1
    }]


def is_internal(environment_id):
    return 'internal' in environment_id


def get_app_type(environment_id, component_name):
    if is_internal(environment_id):
        if re.search(r'(frontend|int-admin)', component_name):
            return 'forms_int'
        else:
            return 'forms_ext_admin'
    else:
        if re.search(r'(admin|frontend-b2c)', component_name):
            return 'forms_biz'
        else:
            return 'forms_ext'


hosts = {
    'forms_int': {
        'api_host': '{ticket}-int.forms-api.test.yandex-team.ru',
        'stand_host': '{ticket}.forms.test.yandex-team.ru',
        'site_url': '{ticket}.forms.test.yandex-team.ru',
        'yastatic_path': '/forms-frontend-int-stand-{ticket}/[basePath]/v[version]',
        'yastatic_front_path': '/forms-frontend-int-stand-{ticket}',
    },
    'forms_ext_admin': {
        'api_host': '{ticket}-ext.forms-api.test.yandex-team.ru',
        'stand_host': '{ticket}.forms.test.yandex.ru',
        'site_url': '{ticket}.forms.test.yandex.ru',
        'yastatic_path': '/forms-frontend-int-stand-{ticket}/[basePath]/v[version]',
        'yastatic_front_path': '/forms-frontend-ext-stand-{ticket}',
    },
    'forms_ext': {
        'api_host': '{ticket}-ext.forms-api.test.yandex.ru',
        'stand_host': '{ticket}.forms.test.yandex.ru',
        'site_url': '{ticket}.forms.test.yandex.ru',
        'yastatic_path': '/forms-frontend-ext-stand-{ticket}/[basePath]/v[version]',
        'yastatic_front_path': '/forms-frontend-ext-stand-{ticket}',
    },
    'forms_biz': {
        'api_host': '{ticket}-biz.forms-api.test.yandex.ru',
        'stand_host': '{ticket}.forms.test.yandex.ru',
        'site_url': '{ticket}.forms.test.yandex.ru/u',
        'yastatic_path': '/forms-frontend-ext-stand-{ticket}/[basePath]/v[version]',
        'yastatic_front_path': '/forms-frontend-ext-stand-{ticket}',
    },
}

domains = {
    'internal': {
        'stand_host': '{ticket}.forms.test.yandex-team.ru',
        'l7path': '/forms-frontend-int-stand-{ticket}/',
    },
    'external': {
        'stand_host': '{ticket}.forms.test.yandex.ru',
        'l7path': '/forms-frontend-ext-stand-{ticket}/',
    },
}


def get_variables(environment_id, stand_ticket, component_name):
    app_type = get_app_type(environment_id, component_name)
    host_data = hosts[app_type]
    ticket = stand_ticket.lower()
    api_host = host_data['api_host'].format(ticket=ticket)
    stand_host = host_data['stand_host'].format(ticket=ticket)
    site_url = host_data['site_url'].format(ticket=ticket)
    yastatic_path = host_data['yastatic_path'].format(ticket=ticket)
    yastatic_front_path = host_data['yastatic_front_path'].format(ticket=ticket)
    return {
        'FORMS_API_HOST': api_host,
        'FORMS_SITE_URL': site_url,
        'FORMS_PREVIEW_HOST': stand_host,
        'YASTATIC_PATH': yastatic_path,
        'YASTATIC_FRONT_PATH': yastatic_front_path,
        'USE_ENVIRONMENT': 'testing',
    }


def get_stand_environment_id(environment_id, stand_ticket):
    stand_name = 'stand-{ticket}'.format(ticket=stand_ticket.lower())
    project, application, _ = environment_id.split('.')
    return '.'.join((project, application.replace('www', 'stands'), stand_name))


def get_stand_dump(environment_id, stand_ticket):
    dump = get_dump(environment_id)
    dump['objectId'] = get_stand_environment_id(environment_id, stand_ticket)
    for component in dump['components']:
        if re.search(r'(admin|frontend)', component['componentName']):
            component['instanceGroups'] = get_instance_groups(1)
            component['properties']['size'] = '1;0.5;64;1'
            variables = get_variables(environment_id, stand_ticket, component['componentName'])
            component['environmentVariables'].update(variables)
        else:
            component['instanceGroups'] = get_instance_groups(0)
    return dump


def get_domains_data(environment_id, stand_ticket):
    domain_type = 'internal' if is_internal(environment_id) else 'external'
    domains_data = domains[domain_type]
    ticket = stand_ticket.lower()
    stand_host = domains_data['stand_host'].format(ticket=ticket)
    l7path = domains_data['l7path'].format(ticket=ticket)
    return [
        {
            'domainName': stand_host,
            'type': 'tools-int-test',
        },
        {
            'domainName': 'yastatic.net',
            'type': 'cdn',
            'l7path': l7path,
        },
    ]


def get_result_url(rc):
    return '{host}/projects/{projectName}/{applicationName}/{name}'.format(host=QLOUD_HOST, **rc)


def create_stand(environment_id, stand_ticket):
    try:
        stand_environment_id = get_stand_environment_id(environment_id, stand_ticket)

        stand_dump = get_stand_dump(environment_id, stand_ticket)
        rc = upload(stand_dump)
        print('Creating %s' % get_result_url(rc))

        for domain_data in get_domains_data(environment_id, stand_ticket):
            create_domain(stand_environment_id, domain_data)
    except requests.HTTPError as e:
        print(e.response.text)


def drop_stand(environment_id, stand_ticket):
    try:
        stand_environment_id = get_stand_environment_id(environment_id, stand_ticket)
        print('Deleting %s' % stand_environment_id)
        drop(stand_environment_id)
    except requests.HTTPError as e:
        print(e.response.text)


environments = {
    'forms_int': 'tools.forms-internal-www.testing',
    'forms_ext_admin': 'tools.forms-internal-www.testing',
    'forms_ext': 'tools.forms-external-www.testing',
    'forms_biz': 'tools.forms-external-www.testing',
}

def get_environments(applications):
    return set(
        environments[app]
        for app in applications
        if app in environments
    )


def main():
    if len(sys.argv) < 3:
        print('Usage: %s {create|drop} stand_ticket [forms_int forms_ext forms_ext_admin forms_biz]' % sys.argv[0])
        return
    command = sys.argv[1]
    stand_ticket = sys.argv[2]
    applications = sys.argv[3:]
    if not applications:
        applications = 'forms_int forms_ext forms_ext_admin forms_biz'.split()

    if command == 'create':
        for environment_id in get_environments(applications):
            create_stand(environment_id, stand_ticket)
    elif command == 'drop':
        for environment_id in get_environments(applications):
            drop_stand(environment_id, stand_ticket)


if __name__ == '__main__':
    main()
