#!/usr/bin/env python

import requests
import argparse
import logging
import sys
import urllib.parse

logger = logging.getLogger(__name__)
logging.basicConfig(stream=sys.stdout, level=logging.INFO)

parser = argparse.ArgumentParser()
parser.add_argument('--gitlab-access-token', required=True)
parser.add_argument('--gitlab-url', required=True)

group_projects = parser.add_mutually_exclusive_group(required=True)
group_projects.add_argument('--repository-names', nargs='+',
                            help='names fo repositories in the form of "namespace/repository-name')
group_projects.add_argument('--all', help='mirror all repositories', action='store_true')
group_projects.add_argument('--users', nargs='+', help='mirror all repositories for the users')
group_projects.add_argument('--groups', nargs='+', help='mirror all repositories for the groups')

args = parser.parse_args()

gitlab_url = args.gitlab_url
gitlab_access_token = args.gitlab_access_token
gitlab_api = f'{gitlab_url}/api/v4'
gitlab_project_url = f'{gitlab_api}/projects'
gitlab_project_by_groups = f'{gitlab_api}/groups'
gitlab_project_by_users = f'{gitlab_api}/users'
projects_all = args.all
projects_users = args.users
projects_groups = args.groups


headers = {
    'Private-Token': gitlab_access_token,
    'cache-control': "no-cache"
}

read_only_branches_param = {'name': '*', 'push_access_level': 0, 'merge_access_level': 0, 'unprotect_access_level': 0}

projects = []

if projects_all:
    logger.info(f'get_projects_url: {gitlab_project_url}')
    r = requests.request("GET", gitlab_project_url, data='', headers=headers)
    projects.extend(r.json())

    while r.links and r.links.get('next') and r.links.get('next').get('url'):
        r = requests.request("GET", r.links.get('next').get('url'), data='', headers=headers)
        projects.extend(r.json())

    logger.info(f'found {len(projects)} projects in GitLab')
elif projects_users:
    for user in projects_users:
        r = requests.request("GET", f'{gitlab_project_by_users}/{user}/projects', data='', headers=headers)
        projects.extend(r.json())

        while r.links and r.links.get('next') and r.links.get('next').get('url'):
            r = requests.request("GET", r.links.get('next').get('url'), data='', headers=headers)
            projects.extend(r.json())

        logger.info(f'found {len(projects)} projects in GitLab for user: {user}')
    if len(projects_users) > 1:
        logger.info(f'found total number of {len(projects)} projects in GitLab for users: {projects_users}')
elif projects_groups:
    for group in projects_groups:
        r = requests.request("GET", f'{gitlab_project_by_groups}/{group}/projects', data='', headers=headers)
        projects.extend(r.json())
        while r.links and r.links.get('next') and r.links.get('next').get('url'):
            r = requests.request("GET", r.links.get('next').get('url'), data='', headers=headers)
            projects.extend(r.json())
        logger.info(f'found {len(projects)} projects in GitLab for group: {group}')
    if len(projects_groups) > 1:
        logger.info(f'found total number of {len(projects)} projects in GitLab for groups: {projects_groups}')
else:
    for path_with_namespace in args.repository_names:
        urlencode_project = f'{gitlab_project_url}/{urllib.parse.quote(path_with_namespace, safe="")}'
        logger.info(f'project: {urlencode_project}')
        r = requests.request("GET",
                             urlencode_project,
                             data='',
                             headers=headers)
        projects.append(r.json())


for p in projects:
    project_id = p['id']
    logger.info(f'project_id: {project_id}')
    gitlab_protected_branches = f'{gitlab_project_url}/{project_id}/protected_branches'
    protected_branches_r = requests.get(gitlab_protected_branches, headers=headers)
    if protected_branches_r:
        for branch in protected_branches_r.json():
            del_r = requests.delete(f'{gitlab_protected_branches}/{branch.get("name")}', headers=headers)
            if del_r:
                logger.info(f'delete current protected branches for project_id: {project_id}')
            else:
                logger.warning(f'delete returned {del_r.status_code} instead of 200-400 '
                               f'for project_id: {project_id}. {del_r.reason}')
        post_r = requests.post(f'{gitlab_protected_branches}', params=read_only_branches_param, headers=headers)
        if post_r.status_code:
            logger.info(f'created read-only for project_id: {project_id}')
        else:
            logger.error(f'did not create the *:no_one protected branch for project_id: {project_id}')

    else:
        logger.info(f'no 200-400 on project_id: {project_id}, got response: {protected_branches_r}')
