#!/usr/bin/env python
import datetime
import os
import sys
import click
import cli_changelog_md

from core_changelog_md.objects.changes import ChangeCollection
from core_changelog_md.objects.version import VersionBlock
from core_changelog_md.common.exceptions import ChangeLogException
from core_changelog_md.objects.changelog import Changelog

from gitlab import Gitlab
from pathlib import Path

from cli_changelog_md.cfg import Config


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


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


@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)).current_version.version.public)
    except ChangeLogException as e:
        click.echo(str(e))
        sys.exit(os.EX_SOFTWARE)


@cli.command(name='git-diff')
@click.option(
    '--file', '-f', default='CHANGELOG.md', show_default=True, help='Changelog file path', type=click.Path(exists=True))
@click.option('--branch', '-b', help='Branch to sync')
def git_diff(file, branch):
    config = Config.load()
    branch = branch if branch else config.git_project.master_branch
    file = Path(file)
    changelog = Changelog.from_file(path=file)
    other_change_log = Changelog.from_str(config.git_project.get_git_file_text(file_name=file.name, branch=branch))
    click.echo(changelog.difference(other_change_log).text())


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


@cli.command(name='unreleased-changes')
@click.option(
    '--file', '-f', default='CHANGELOG.md', show_default=True, help='Changelog file path', type=click.Path(exists=True))
def unreleased_changes(file):
    """
    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:
        click.echo(changelog.unreleased.text())


@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(name='git-login')
@click.option("--token", '-t', prompt=True, hide_input=True)
@click.option('--host', '-h', help="gitlab server")
def git_login(host, token):
    try:
        Gitlab(host, private_token=token).auth()
    except Exception as e:
        raise click.BadParameter("Host or token incorrect!")

    config = Config.load(git_token=token)
    config.add_gitlab_login(host=host, token=token)
    config.save_config()


@cli.command()
def config():
    click.echo(open(Config.PROFILE_PATH, 'r', encoding="UTF8").read())


@cli.command(name='git-sync')
@click.option('--branch', '-b', help='Branch to sync')
@click.option(
    '--file', '-f', default='CHANGELOG.md', show_default=True, help='Changelog file path', type=click.Path(exists=True))
@click.option('--push', '-p', help='Push sync changelog', is_flag=True)
def git_sync(file, branch, push):
    config = Config.load()
    branch = branch if branch else config.git_project.master_branch
    file = Path(file)
    changelog = Changelog.from_file(path=file)
    other_change_log = Changelog.from_str(config.git_project.get_git_file_text(file_name=file.name, branch=branch))
    changelog.sync(other_change_log)
    changelog.save()
    if push:
        config.git_project.push_changelog(changelog=changelog, file_name=file.name)
        click.echo(f'pushed in {config.git_project.branch}')


@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))
@click.option('--push', '-p', help='Push sync changelog', is_flag=True)
def release(file, bump_major, push):
    """
    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:
        file = Path(file)
        next_version = VersionBlock(version=changelog.next_version, date=datetime.datetime.now().date())
        next_version.change_blocks = changelog.unreleased.change_blocks
        changelog.unreleased.change_blocks = ChangeCollection()
        changelog.versions.append(next_version)
        changelog.save(path=file)
        click.echo(f'Released version {next_version.version.public} is added in {file.name}')
        if push:
            config = Config.load()
            config.git_project.push_changelog(changelog=changelog, file_name=file.name)
            click.echo(f'pushed in {config.git_project.branch}')
    else:
        click.echo("Unreleased Block is empty!")


if __name__ == '__main__':
    cli()
