#!/usr/bin/python
# -*- encoding: utf-8 -*-

import sys
import os

sys.path.insert(0, '/opt/direct-py/startrek-python-client-sni-fix')
from startrek_client import Startrek

import yaml
import json

pathlist = ["/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", "/sbin", "/bin", "/usr/games", "/usr/local/games"]
os.environ["PATH"] = os.pathsep.join(pathlist)

STARTREK_TOKEN_FILE = '/etc/direct-tokens/startrek'
SCRIPT_NAME = os.path.basename(__file__)

with open(STARTREK_TOKEN_FILE) as st_fd:
    startrek_token = st_fd.readline().strip()

APPS_CONF_FILE = "/etc/yandex-direct/direct-apps.conf.yaml"

with open(APPS_CONF_FILE) as apps_fd:
    apps_dict = yaml.load(apps_fd)['apps']

component2app = {apps_dict[app]['tracker-component']: app for app in apps_dict if 'tracker-component' in apps_dict[app]}

startrek_client = Startrek(token=startrek_token, useragent=SCRIPT_NAME)

RELEASE_STATUSES = [
    "Testing",
    "ReadyForTest",
]

QUEUES = [
    "DIRECT",
    "TESTIRT",
]

TESTING_FIELDS = {'java-api5': 'java-api'}
TICKET_TAG = u'release_testing'
TICKET_TAG_PREFIX = TICKET_TAG + u'_'
APPS_WITH_TESTING_FIELD = {'java-api5', 'java-web', 'java-intapi', 'java-jobs', 'java-logviewer'}


def find_tickets(release):
    """
    Находит тикеты вошедшие в релиз и требующие тестирования. Подразумевается, что тикеты привязанные к релизному
    тикету -- про код, который выкладывается в релизе.

    Другие релизы, привязанные к релизному тикету, а так же тикеты кроссрелизных зависимостей игнорируются.
    """

    app = get_release_app(release)
    if not app:
        return []

    query = u'Queue: %s Relates: %s Type: !Release Tags: !кроссрелизные_зависимости' % (u", ".join(QUEUES), release.key)
    if apps_dict[app]['type'] == 'arcadia-java' and apps_dict[app]['tracker-affected-app']:
        query += u' "Affected apps": "%s"' % apps_dict[app]['tracker-affected-app']

    tickets = [issue.key for issue in startrek_client.issues.find(query)]

    skip_tag = set()
    if release.testComment:
        problems = json.loads(release.testComment)
        skip_tag |= set(
            ticket for ticket in problems
            if isinstance(problems[ticket], dict) and (problems[ticket].get('relevant', {}).get('status', '') == "No"
                or problems[ticket].get('significant', {}).get('status', '') == "No")
        )

    return [ticket for ticket in tickets if ticket not in skip_tag]


def get_release_app(release):
    """
    Получает идентификатор приложения, для которого сделан релиз

    :return: идентификатор приложения, например 'java-web'
    """
    for comp in release.components:
        if comp.display in component2app:
            return component2app[comp.display]
    return None


def get_testing_tag_by_app(app):
    return TICKET_TAG_PREFIX + app


def run():
    releases = startrek_client.issues.find(
        u'Queue: DIRECT Type: Release Status: %s "Sort by": key desc' % (u", ".join(RELEASE_STATUSES))
    )

    tickets_to_tag = []
    releases_by_apps = {}

    for release in releases:
        app = None
        for component in release.components:
            if component.display in component2app:
                app = component2app[component.display]
                if app not in releases_by_apps:
                    releases_by_apps[app] = []
                releases_by_apps[app].append(release)
                break

    all_tickets_to_tag = []

    for app in apps_dict:
        tickets_to_tag = []

        metatracker_tickets = []
        for release in releases_by_apps.get(app, []):
            tickets_to_tag.extend(find_tickets(release))

        tickets_to_tag = set(tickets_to_tag) - set(metatracker_tickets)
        all_tickets_to_tag.extend(list(tickets_to_tag))

        testing_tag_by_app = get_testing_tag_by_app(app)
        tickets_to_untag = set(
            issue.key for issue in startrek_client.issues.find(
                u'Queue: %s Tags: %s' % (u", ".join(QUEUES), testing_tag_by_app)
            ) if issue.key not in tickets_to_tag
        )

        startrek_client.bulkchange.update(
            list(tickets_to_tag),
            tags={'add': [testing_tag_by_app]}
        ).wait()

        startrek_client.bulkchange.update(
            list(tickets_to_untag),
            tags={'remove': [testing_tag_by_app]}
        ).wait()

    all_tickets_to_tag = set(all_tickets_to_tag)
    all_tickets_to_untag = set(
        issue.key for issue in startrek_client.issues.find(
            u'Queue: %s Tags: %s' % (u", ".join(QUEUES), TICKET_TAG)
        ) if issue.key not in all_tickets_to_tag
    )

    startrek_client.bulkchange.update(
        list(all_tickets_to_tag),
        tags={'add': [TICKET_TAG]}
    ).wait()

    startrek_client.bulkchange.update(
        list(all_tickets_to_untag),
        tags={'remove': [TICKET_TAG]}
    ).wait()

    return


if __name__ == '__main__':
    run()

