from argparse import ArgumentParser
from importlib.metadata import version  
import os
import toml

from git import Repo

version_components= {'major': 0, 'minor': 1, 'patch': 2}

def get_parser():
    parser = ArgumentParser(description='Bump version')
    parser.add_argument('component', type=str, choices=version_components.keys(), help='Version component bump')
    parser.add_argument('--commit', action='store_true', help='Execute the updates')
    
    return parser


def main():
    parser = get_parser()
    
    opts = parser.parse_args()
    if opts.component not in version_components:
        parser.print_help()
        return

    toml_str= read_current_toml()

    version_str = toml_str['project']['version']
    version_parts = version_str.split('.')

    version_parts[version_components[opts.component]] = str(int(version_parts[version_components[opts.component]]) + 1)
    new_version = '.'.join(version_parts)

    toml_str['project']['version'] = new_version

    print(f"{version_str} + {opts.component} => {new_version}")

    release = Release(version_str, new_version, opts.component, opts.commit)

    os.makedirs('release', exist_ok=True)

    release.bump_version()
    release.write_changelog()
    
    release.write_changes()
    release.create_tag()
    release.push()

def read_current_toml():
    with open('pyproject.toml', 'rt') as f:
        toml_content = toml.loads(f.read())
    return toml_content


def get_release_changes(from_version, to_version="HEAD"):
    r = Repo('.')

    prefix="release/"
    if to_version.upper().strip() == "HEAD":
        prefix=""

    o = r.git.log(f"release/{from_version}...{prefix}{to_version}", oneline=True)
    return o


class Release():
    def __init__(self, from_version, to_version, bump_type, commit=False):
        self.from_version = from_version
        self.to_version = to_version
        self.bump_type = bump_type
        self.commit = commit

    def bump_version(self):
        toml_content = read_current_toml()
        toml_content['project']['version'] = self.to_version

        with open('pyproject.toml', 'wt') as f:
            f.write(toml.dumps(toml_content))
        with open("release/version.new.txt", 'wt') as f:
            f.write(self.to_version)
        with open("release/version.old.txt", 'wt') as f:
            f.write(self.from_version)
        with open("release/changes.txt", 'wt') as f:
            f.write(self.get_changes())

    def write_changes(self):
        
        if self.commit:
            r = Repo('.')
            r.git.add('pyproject.toml')
            r.git.add('CHANGELOG.md')
            r.commit(f"Release [{self.bump_type}] version to {self.to_version}")

    def create_tag(self):
        if self.commit:
            r = Repo('.')
            r.git.tag(f"release/{self.to_version}")
    
    def push(self):
        if self.commit:
            r = Repo('.')
            r.git.push('origin', '--tags')

    def get_changes(self, head=True):
        return get_release_changes(self.from_version, 'HEAD' if head else self.to_version)
    
    def write_changelog(self):
        existing = ""
        if os.path.exists('CHANGELOG.md'):
            with open('CHANGELOG.md', 'rt') as f:
                existing = f.read()
        
        with open('CHANGELOG.md', 'wt') as f:
            f.write(f"## {self.to_version}\n")
            f.write(self.get_changes())
            f.write("\n\n")
            f.write(existing)

if __name__ == '__main__':
    main()
    