import os
import sys

import requests

token = os.getenv("GLOBAL_CICD_GIT_TOKEN")
headers = {
    "Authorization": f"Bearer {token}",
    "Accept": "application/vnd.github.v3+json"
}


def get_branch_protection(repo: str, branch: str):
    api_url = f"https://api.github.com/repos/{repo}/branches/{branch}/protection"
    print(f"api url: {api_url}")
    response = requests.get(api_url, headers=headers)
    json_res = response.json()
    if response.status_code == 200:
        print("OK")
        return json_res
    else:
        print("Error to get branch protection rules:", response.status_code, response.text)
    return None


def update_branch_protection(repo: str, branch: str, data) -> None:
    api_url = f"https://api.github.com/repos/{repo}/branches/{branch}/protection"
    response = requests.put(api_url, headers=headers, json=data)
    json_res = response.json()
    if response.status_code == 200:
        print("update branch success")
    else:
        print("Error in update branch protection:", response.status_code, json_res)
        os.system(f'echo ":stop: Error in update branch protection " >> $GITHUB_STEP_SUMMARY')
        exit(1)


def get_bool_enabled(key_name, current_rules):
    if current_rules.get(key_name):
        small_dict = current_rules[key_name]
        return small_dict.get("enabled")


def get_required_status_checks(current_rules):
    strict = False
    checks = []
    if current_rules.get('required_status_checks'):
        if current_rules['required_status_checks'].get('strict'):
            strict = current_rules['required_status_checks']['strict']
        if current_rules['required_status_checks'].get('checks'):
            checks = current_rules['required_status_checks']['checks']
    return strict, checks


def get_required_pull_request_reviews(current_rules):
    dismiss_stale_reviews = False
    require_code_owner_reviews = False
    require_last_push_approval = False
    required_approving_review_count = 0
    bypass_pull_request_allowances = None
    if current_rules.get('required_pull_request_reviews'):
        pr_review = current_rules['required_pull_request_reviews']
        if pr_review.get('dismiss_stale_reviews'):
            dismiss_stale_reviews = pr_review['dismiss_stale_reviews']
        if pr_review.get('require_code_owner_reviews'):
            require_code_owner_reviews = pr_review['require_code_owner_reviews']
        if pr_review.get('require_last_push_approval'):
            require_last_push_approval = pr_review['require_last_push_approval']
        if pr_review.get('required_approving_review_count'):
            required_approving_review_count = pr_review['required_approving_review_count']
        if pr_review.get('bypass_pull_request_allowances'):
            if pr_review['bypass_pull_request_allowances'].get('users'):
                users = [x['login'] for x in pr_review['bypass_pull_request_allowances']['users']]
                bypass_pull_request_allowances = {"users": users}
    pr_review_dict = {
        "dismiss_stale_reviews": dismiss_stale_reviews,
        "require_code_owner_reviews": require_code_owner_reviews,
        "require_last_push_approval": require_last_push_approval,
        "required_approving_review_count": required_approving_review_count,
        "bypass_pull_request_allowances": bypass_pull_request_allowances
    }
    return pr_review_dict


def create_payload(lock, current_rules):
    data = {
        "required_status_checks": {
            "strict": None,
            "checks": [],
        },
        "enforce_admins": None,
        "required_pull_request_reviews": None,
        "restrictions": None,
        "lock_branch": lock
    }
    enforce_admins = get_bool_enabled("enforce_admins", current_rules)
    restrictions = get_bool_enabled("restrictions", current_rules)
    required_status_checks_strict, required_status_checks_checks = get_required_status_checks(current_rules)
    required_pull_request_reviews = get_required_pull_request_reviews(current_rules)
    data['enforce_admins'] = enforce_admins
    data['restrictions'] = restrictions
    data['required_status_checks']['strict'] = required_status_checks_strict
    data['required_status_checks']['checks'] = required_status_checks_checks
    data['required_pull_request_reviews'] = required_pull_request_reviews
    return data


# worked_data_example = {
#     "required_status_checks": {
#         "strict": False,
#         "checks": [{"context": "jira_ticket_fields_check", "app_id": 15368}],
#     },
#     "enforce_admins": False,
#     "required_pull_request_reviews": {
#         'dismiss_stale_reviews': False,
#         'require_code_owner_reviews': False,
#         'require_last_push_approval': False,
#         'required_approving_review_count': 1,
#         'bypass_pull_request_allowances': {
#             'users': ['sayuser', 'shaylevin89']
#         }
#     },
#     "restrictions": None,
#     "lock_branch": True
# }

if __name__ == '__main__':
    if len(sys.argv) > 2:
        repo_name = sys.argv[3].replace("repo_name=", "", 1)
        if repo_name == "":
            print(f"error to get repo name")
            exit(1)
        main_branch_input = sys.argv[1]
        main_branch = main_branch_input.replace("main_branch=", "", 1)
        if main_branch == "":
            print(f"error to get main branch name")
            exit(1)
        lock_input = sys.argv[2]
        lock = lock_input.replace("lock=", "", 1)
        if lock == "":
            print(f"error to get desired lock status, only (true|false)")
            exit(1)
        if lock.lower() == "true":
            lock = True
        elif lock.lower() == "false":
            lock = False
        else:
            print(f"error to get desired lock, only (true|false) allowed")
            exit(1)
    else:
        print(f"error to get args <main branch name> and <lock> (True|False)")
        exit(1)

    branch_protection = get_branch_protection(repo_name, main_branch)
    if not branch_protection:
        print("error in get branch protection")
        exit(1)

    new_data = create_payload(lock, branch_protection)
    print("new payload to update protection branch rules:")
    print(new_data)
    update_branch_protection(repo_name, main_branch, new_data)

