#!/usr/bin/python3

import argparse
import re
import subprocess
import sys

from github import Github
import os


def main():
    # set up parser
    parser = argparse.ArgumentParser()
    parser.add_argument('-v', '--version', type=str, help='Version to release.')
    parser.add_argument('-t', '--token', type=str, help='GitHub access token.',
                        default=os.getenv('GITHUB_ACCESS_TOKEN', None))
    args = parser.parse_args()

    # check github access token
    if args.token is None:
        print('No GitHub access token found.')
        return 1

    # get repo name
    repo_remote = shell('git config --get remote.origin.url')
    if not repo_remote:
        print("Not a git repository.")
        sys.exit(1)
    m = re.search(r'github\.com[:/](.*)\.git$', repo_remote)
    if m is None:
        print('Could not identify GitHub repository.')
        return 1
    repo_name = m.group(1)
    repo_owner = shell('git config --get user.name')
    print(f'Repository:      {repo_name}')
    print(f'User:            {repo_owner}')

    # pyproject.toml?
    if not os.path.exists('pyproject.toml'):
        print('No pyproject.toml found.')
        return 1

    # Poetry?
    try:
        shell('poetry')
    except subprocess.CalledProcessError:
        print('No poetry found.')
        return 1

    # current version
    version = get_current_version()
    print(f'Current version: {version}')

    # connect to GitHub
    print()
    print('Connecting to GitHub...')
    gh = Github(args.token)
    print('Fetching repository...')
    repo = gh.get_repo(repo_name)
    branches = repo.get_branches()
    branch_names = [b.name for b in branches]
    if 'develop' not in branch_names:
        print('No develop branch found.')
        return 1
    main_branch = 'main'
    if main_branch not in branch_names:
        main_branch = 'master'
        if main_branch not in branch_names:
            print('No main/master branch found.')
            return 1

    # currently in develop?
    cur_branch = shell('git rev-parse --abbrev-ref HEAD')
    if cur_branch != 'develop':
        print('Current branch is not develop.')
        return 1

    # print plan
    print()
    print('Will perform the following tasks:')
    if args.version is None:
        print(f'1. Set new version using "poetry version patch"')
        set_version = 'patch'
    else:
        print(f'1. Set new version using "poetry version {args.version}"')
        set_version = args.version
    print(f'2. Commit and pull change.')
    print(f'3. Create PR develop -> {main_branch}')
    print(f'4. Merge PR')
    print(f'5. Create tag and release with new version')

    # continue
    if input('Continue [y/N]') not in 'yY':
        return 0

    # set new version
    print()
    print('Setting new version...')
    shell(f'poetry version {set_version}')
    version = get_current_version()
    print(f'New version: {version}')

    # commit it
    shell(f'git commit -m "v{version}" pyproject.toml')
    shell(f'git push')

    # shortcuts
    title = f'v{version}'
    body = f'version {version}'

    # create PR
    print('Creating PR...')
    pr = repo.create_pull(title=title, body=body, head='develop', base=main_branch)

    # merge PR
    print('Merging PR...')
    pr.merge(commit_title=title, commit_message=body)

    # get last commit
    print('Fetching last commit...')
    commit = repo.get_commits()[0]
    print(f'Commit is {commit.sha}.')

    # tag & release
    print('Create tag and release...')
    repo.create_git_tag_and_release(tag=title, tag_message=body, release_name=title, release_message=body,
                                    object=commit.sha, type='commit')
    print('Done.')


def shell(cmd, check=True):
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, check=check)
    return result.stdout.decode('utf-8').strip()


def get_current_version():
    return shell('poetry version').split()[1].strip()


if __name__ == '__main__':
    code = main()
    sys.exit(code)