#!/usr/bin/env python
import os
import re
import sys

import click
from cli_changelog_md.exceptions import ChangeLogException

import cli_changelog_md

from cli_changelog_md.enums import ChangeTypes
from cli_changelog_md.git import get_branch
from cli_changelog_md.objects import Changelog, VersionBlock, ChangeBlock


@click.group()
@click.version_option(version=cli_changelog_md.__version__)
def cli() -> None:
    pass


def validate_git(ctx, param, value):
    current_path = os.path.abspath(os.getcwd())
    git_path = os.path.join(current_path, '.git')
    if value and not os.path.exists(git_path):
        raise click.BadParameter(f"Not found .git repository in current folder {current_path}")
    return True


@cli.command()
@click.option(
    '--file', '-f', default='CHANGELOG.md', show_default=True, help='Changelog file path', type=click.Path(exists=True))
def current(file):
    """
    Echo current version
    """
    try:
        click.echo(Changelog.from_file(os.path.realpath(file)).versions[1].version.public)
    except ChangeLogException as e:
        click.echo(str(e))
        sys.exit(os.EX_SOFTWARE)


@cli.command(name='next')
@click.option(
    '--file', '-f', default='CHANGELOG.md', show_default=True, help='Changelog file path', type=click.Path(exists=True))
def _next(file):
    """
    Echo next version
    """
    try:
        click.echo(Changelog.from_file(os.path.realpath(file)).next_version())
    except ChangeLogException as e:
        click.echo(str(e))
        sys.exit(os.EX_SOFTWARE)


@cli.command()
@click.option(
    '--file', '-f', default='CHANGELOG.md', show_default=True, help='Changelog file path', type=click.Path(exists=True))
def bump(file):
    """
    Echo next major version
    """
    try:
        click.echo(Changelog.from_file(os.path.realpath(file)).bump_version())
    except ChangeLogException as e:
        click.echo(str(e))
        sys.exit(os.EX_SOFTWARE)


@cli.command()
@click.option(
    '--file', '-f', default='CHANGELOG.md', show_default=True, help='Changelog file path', type=click.Path(exists=True))
@click.option(
    '--change-type', '-c', default=ChangeTypes.FEATURED.tag, show_default=True,
    type=click.Choice(ChangeTypes.accept_tag(), case_sensitive=False))
@click.option(
    '--branch', '-b', help='Add branch name as change line', is_flag=True, type=click.UNPROCESSED, callback=validate_git)
@click.option(
    '--detect_issue', '-d', help='Detect issue name in branch', is_flag=True, type=click.UNPROCESSED, callback=validate_git)
@click.argument('text', default='aaa')
def add(file, text, change_type, branch, detect_issue):
    """
    Add change line in target change block
    """
    try:
        changelog = Changelog.from_file(os.path.realpath(file))
    except ChangeLogException as e:
        click.echo(str(e))
        sys.exit(os.EX_SOFTWARE)

    if branch or detect_issue:
        current_path = os.path.abspath(os.getcwd())
        git_path = os.path.join(current_path, '.git')
        text = get_branch(git_path=git_path).strip()

        if detect_issue:
            data = re.findall(r'(^[a-zA-Z]+-\d+)[-_]?(.+)', text)
            if data:
                project, text_part = data[0]
                text_part = ' '.join(re.findall(r'[a-zA-Z0-9]+', text_part))
                text = '{0} {1}'.format(project, text_part)
            else:
                click.echo(f"No detect issue in branch name \"{text}\"!")
                return

    changelog.last_version().add(text, change_type=ChangeTypes.get_by_tag(change_type))
    changelog.save()


@cli.command()
@click.option('--bump-major', '-b', help='Up major version', is_flag=True)
@click.option(
    '--file', '-f', default='CHANGELOG.md', show_default=True, help='Changelog file path', type=click.Path(exists=True))
def release(file, bump_major):
    """
    Make release changelog
    """
    try:
        changelog = Changelog.from_file(os.path.realpath(file))
    except ChangeLogException as e:
        click.echo(str(e))
        sys.exit(os.EX_SOFTWARE)
    if changelog.has_unreleased_changes:
        next_version_row = changelog.bump_version() if bump_major else changelog.next_version()
        next_version = VersionBlock(version_row=next_version_row)
        next_version.changes = changelog.unreleased.changes
        changelog.unreleased.changes = []
        changelog.add(next_version)
        changelog.save()
        click.echo(f'Released version {next_version.version.public} is added in {os.path.basename(file)}')
    else:
        click.echo("Unreleased Block is empty!")


if __name__ == '__main__':
    cli()
