#!/usr/bin/env python3
"""
This is script for disabling merging to spade/events mainline
in case of an emergency.
"""

import argparse
import os
import getpass
import requests

import build


def get_validation_status_check_build_url(commit_sha, owner, repo,
                                        username, password, session):
    """
        Get a jenkins build url for sha, it doesn't really matter which
        one because rebuilding any of them will rebuild on the latest
        version of the branch. This is helpful because we can pass in
        this url when we invalidate status checks, so users can easily
        rebuild when the pipeline is unfrozen.
    """
    url = f'https://git.xarth.tv/api/v3/repos/{owner}/{repo}/statuses/{commit_sha}'
    response = session.get(url, auth=(username, password))
    for status in response.json():
        return status['target_url']
    return None


def get_latest_commit_on_branch(owner, repo, branch,
                                username, password,
                                session):
    """Get latest commit on a branch."""

    # This returns the commits in reverse chronological order, so the first one returned
    # should be the latest one.
    commits = f'https://git.xarth.tv/api/v3/repos/{owner}/{repo}/'+\
                f'commits?sha={branch}&page=1&per_page=1'
    response = session.get(commits, auth=(username, password))
    return response.json()[0]


def get_all_branches(owner, repo, username, password, session):
    """Get all branches for a repo"""
    page = 1
    branch_url = f'https://git.xarth.tv/api/v3/repos/{owner}/{repo}/branches?page={page}'
    response = session.get(branch_url, auth=(username, password))
    branches = set()
    while len(response.json()) != 0:
        for branch in response.json():
            branches.add(branch["name"])
        page += 1
        branch_url = f'https://git.xarth.tv/api/v3/repos/{owner}/{repo}/branches?page={page}'
        response = session.get(branch_url, auth=(username, password))
    return branches


def fail_status_check(owner, repo, username, password, session, commit_sha):
    """Fail the validate status check for a commit"""
    target_url = get_validation_status_check_build_url(commit_sha, owner,
                            repo, username, password, session)
    payload = {
        'state': 'failure',
        'description': 'Merging blocked',
        'target_url': target_url,
        'context': 'spade-schema-registry-validate'
    }
    invalidation_url = f'https://git.xarth.tv/api/v3/repos/{owner}/{repo}/statuses/{commit_sha}'
    response = session.post(invalidation_url, json=payload, auth=(username, password))
    if response.status_code < 200 or response.status_code >= 300:
        raise Exception(f'Problem invalidating status checks for {commit_sha} {response.text}')


def jenkins_job_op(action='enable'):
    """Disable or enable the spade-schema-registry-validate job"""
    disable_url = f'https://jenkins-og.xarth.tv/job/spade-schema-registry-validate/{action}'
    jenkins_username = os.getenv('JENKINS_USER')
    jenkins_token = os.getenv('JENKINS_API_TOKEN')
    if jenkins_username == '' or jenkins_token == '':
        raise Exception('please make sure the env vars JENKINS_USER and JENKINS_API_TOKEN are set')
    response = requests.post(disable_url, auth=(jenkins_username, jenkins_token))
    if response.status_code < 200 or response.status_code >= 400:
        raise Exception(f'error disabling validation job {response.text}')


def main():
    parser = argparse.ArgumentParser(description=
        'Disable or enable merging to spade/events mainline branch by non-admin users')
    parser.add_argument('action', metavar='ACTION', type=str,
            help='The action to be taken, valid options are enable and disable')
    args = parser.parse_args()
    if args.action == 'enable':
        print('Enabling jenkins job spade-schema-registry-validate')
        jenkins_job_op('enable')
        print('Done enabling jenkins job spade-schema-registry-validate')
    elif args.action == 'disable':
        print('Disabling jenkins job spade-schema-registry-validate')
        jenkins_job_op('disable')
        print('Done disabling jenkins job spade-schema-registry-validate')
        username = os.getenv('TF_VAR_namespace')
        password = getpass.getpass(prompt='What\'s your github password? ')
        session = build.create_midway_auth_session()
        owner = 'spade'
        repo = 'events'
        branches = get_all_branches(owner, repo, username, password, session)
        for branch in branches:
            if branch != 'mainline':
                commit = get_latest_commit_on_branch(
                        owner, repo, branch, username, password, session)
                sha = commit["sha"]
                print(f'Invalidating status check for commit {sha} in branch {branch}')
                fail_status_check(owner, repo, username, password, session, sha)
                print(f'Done invalidating status check for commit {sha} in branch {branch}')
        return
    else:
        raise Exception(f'Unknown pipeline action {args.action}.'+\
                        ' Valid options are enable and disable')


if __name__ == '__main__':
    main()
