import pkg_resources
import re

from xml.dom import minidom

# The relative path from this file.
path_to_coverage_xml = pkg_resources.resource_filename(__name__, '../coverage.xml')
path_to_readme = pkg_resources.resource_filename(__name__, '../README.md')

# When the coverage badge is clicked this is a link you're taking to.
url_link = "https://github.com/DarrenHaba/privateprefs/actions"


def get_coverage_percentage() -> int:
    """
    Gets the total coverage percent from the coverage.xml file generated by pytest.
    :return: The total code coverage percentage.
    """
    coverage_xml_doc = minidom.parse(path_to_coverage_xml)
    elements = coverage_xml_doc.getElementsByTagName('coverage')
    coverage_decimal = elements[0].attributes['line-rate'].value
    coverage_percentage = int(float(coverage_decimal) * 100)
    return coverage_percentage


def get_readme_str() -> str:
    """
    Reads/Gets the README.md file as a text string
    :return: The README.md as a string
    """
    with open(path_to_readme, "r") as file:
        readme_str = file.read()
        return readme_str


def set_readme_str(readme_str: str) -> None:
    """
    Writs/Sets the README.md from a text string
    :return: None
    """
    with open(path_to_readme, "w") as file:
        file.write(readme_str)


def get_badge_link(percent: int,
                   link: str,
                   title: str = "Coverage",
                   color: str = None,
                   symbol: str = "%25",
                   green: str = "31c653",
                   yellow: str = "yellow",
                   red: str = "red") -> str:
    """
    Generates a custom badge using the shields.io API, we manually set the parameters to make
    this a coverage badge, but we could make any kind of badge using different parameters.
    See docs here: https://shields.io/category/coverage
    :param percent: The code coverage percentage
    :param link: The URL opened when badge is clicked
    :param title: The text/title on the left side of the badge
    :param color: The badge color, if set the badge will never change from this color
    :param symbol: The symbol appended to the end of the percentage, defaults to "%25" (for percentage)
    :param green: The badge color when coverage percent is over 85%
    :param yellow: The badge color when coverage percent is between 60% and 85%
    :param red: The badge color when coverage percent is under 60%
    :return: A string that will show up as a badge in README.md file
    """
    if color is None:
        if 85 < percent <= 100:
            color = green
        elif 60 < percent <= 85:
            color = yellow
        else:
            color = red
    return f"[![Pytest - Coverage](https://img.shields.io/badge/{title}-{percent}{symbol}-{color})]({link})"


def generate_badge() -> None:
    """
    Generates a coverage badge, searches and replaces the existing badge in the README.md file
    :return: None
    """
    pct = get_coverage_percentage()
    regex_pattern = r"\[\!\[Pytest - Coverage\].*"
    new_readme_str = re.sub(regex_pattern, get_badge_link(pct, url_link), get_readme_str())
    set_readme_str(new_readme_str)


if __name__ == "__main__":
    # When the CI runs this module, so we need to trigger the badge generator here.
    generate_badge()
