import os
import sys
from dataclasses import dataclass
from typing import Union

from actions_logging.app_logging import logger
from github.env import exit_on_error_and_write_summary, write_github_env, write_github_summary, get_required_env_var
from github.github_apis import get_tags
from git.constants import MS_TAG_VERSION, VERSION_TO_DEPLOY, NEW_VERSION_NO_DIR
from master.constants import INIT_VERSION


@dataclass()
class Version:
    major: int
    minor: int
    patch: int

    def bump_one(self, severity: str):
        try:
            if not severity or severity.lower() == "patch":
                self.patch += 1
            elif severity.lower() == "major":
                self.major += 1
                self.minor = 0
                self.patch = 0
            elif severity.lower() == "minor":
                self.minor += 1
                self.patch = 0
            else:
                exit_on_error_and_write_summary(f"ERROR - severity {severity} is not valid")
        except Exception as e:
            exit_on_error_and_write_summary(f"error in bump_one: {e}")

    def __str__(self):
        return f"v{self.major}.{self.minor}.{self.patch}"

    def __repr__(self):
        return f"v{self.major}.{self.minor}.{self.patch}"

    def __gt__(self, other):
        return self.gt(other)

    def __lt__(self, other):
        if self == other:
            return False
        return not self.gt(other)

    def gt(self, other):
        if self.major > other.major:
            return True
        elif self.major == other.major:
            if self.minor > other.minor:
                return True
            elif self.minor == other.minor:
                if self.patch > other.patch:
                    return True
        return False


def get_version(tag_name: str, suffix: str = ""):
    """
    take string and and optional dir name and return Version object
    """
    semver = tag_name
    if suffix:
        if f"-{suffix}" not in tag_name:
            return None
        split_version = tag_name.split(f"-{suffix}")
        if split_version[1]:
            return None
        semver = split_version[0]
    if semver and semver[0] != "v":
        return None
    parts = semver[1:].split(".")
    if len(parts) != 3:
        return None
    if not parts[-1].isdigit():
        return None
    else:
        try:
            v = Version(int(parts[0]), int(parts[1]), int(parts[2]))
            return v
        except Exception as e:
            logger.warning(f"couldn't created version from tag {tag_name} with error: {e}")
            return None


def get_git_high_tags(repo, dir_name="") -> Union[Version , None]:
    try:
        logger.debug(f"getting high tags for repo {repo} and tag suffix {dir_name}")
        full_tags = get_tags(repo)
        logger.debug(f"got {len(full_tags)} tags")
        tags_to_get_version = full_tags
        if dir_name:
            tags_to_get_version = [tag for tag in full_tags if f"-{dir_name}" in tag]
        tags = []
        for tag in tags_to_get_version:
            version_tag = get_version(tag, suffix=dir_name)
            if version_tag:
                tags.append(version_tag)
        if tags:
            return max(tags)
        else:
            return None
    except Exception as e:
        exit_on_error_and_write_summary(f"error in get git high tags- {e}")


def main():
    if len(sys.argv) > 1:
        full_repo_name = sys.argv[1]
    else:
        full_repo_name = get_required_env_var("GITHUB_REPOSITORY")
    logger.info(f'repo name: {full_repo_name}')
    is_multi_service_repo = os.getenv("IS_MULTI_SERVICE_REPO", 'false') == 'true'
    tag_suffix = ""
    if is_multi_service_repo:
        tag_suffix = get_required_env_var('SVC_NAME')
        logger.info(f"tag suffix: {tag_suffix}")
    version = get_git_high_tags(full_repo_name, dir_name=tag_suffix)
    if not version:
        version = get_version(INIT_VERSION)
    else:
        severity = get_required_env_var('SEMVER_LEVEL')
        logger.info(severity)
        version.bump_one(severity)
    if tag_suffix:
        tag = f"{version}-{tag_suffix}"
    else:
        tag = str(version)

    logger.info(f"new ms version: {tag}")
    logger.info(f"new ms version without dir: {version}")
    write_github_env(str(version), VERSION_TO_DEPLOY)
    write_github_env(str(version), NEW_VERSION_NO_DIR)
    write_github_env(tag, MS_TAG_VERSION)
    write_github_summary(f":trophy: new version created: **{version}**")


if __name__ == '__main__':
    main()
