import re
import unittest

import git

from puma import version
from puma.utils import PROJECT_ROOT


def get_current_branch_name() -> str | None:
    """
    Get the name of the current Git branch.
    If the repo is in a detached state it is not in a branch and this method returns None.
    :return: The name of the current branch.
    """
    try:
        repo = git.Repo(search_parent_directories=True)
        return repo.active_branch.name
    except TypeError:
        return None

def extract_issue_number(branch_name) -> str:
    """
    Get the issue number of the current Git branch. Assumes the structure is [ISSUE_NB]-[ISSUE_TITLE], as generated by
    GitHub.
    :param branch_name: Branch name to get the issue number from.
    :return: issue number
    """
    # Use regex to find the issue number at the start of the branch name
    match = re.match(r'^(\d+)-', branch_name)
    if match:
        return match.group(1)  # Return the captured issue number
    else:
        raise ValueError('Invalid issue number, please check that your branch name starts with the issue number and a'
                         ' dash.')

def read_release_notes(file_path: str) -> list[str]:
    """
    Read the content of the release notes file.
    :param file_path: The path to the release notes file.
    :return: The content of the release notes file.
    """
    with open(file_path, 'r') as file:
        return file.readlines()


class TestReleaseNotes(unittest.TestCase):
    def setUp(self):
        self.branch_name = get_current_branch_name()

        # If running on the main branch, skip these tests because branch naming conventions do not apply.
        if self.branch_name == "main":
            self.skipTest("Skipping release-notes tests on the main branch")
        # Also skip if in a detached state
        if self.branch_name is None:
            self.skipTest("Skipping release-notes tests when not on a branch")

        self.issue_number = extract_issue_number(self.branch_name)
        self.release_notes_path = f"{PROJECT_ROOT}/RELEASE_NOTES"
        self.release_notes = read_release_notes(self.release_notes_path)

    def test_branch_in_release_notes(self):
        self.assertIn(f"{self.issue_number}. ",
                      "\n".join(self.release_notes),
                      f"Issue number {self.issue_number} was not found in the release notes, please add an entry "
                      f"for this issue.")

    def test_version_in_release_notes_same_as_setup(self):
        first_line = self.release_notes[0]
        match = re.search(r'(\d+\.\d+\.\d+)', first_line)
        first_version_in_release_notes = match.group(1) if match else None
        self.assertIsNotNone(first_version_in_release_notes,
                             "The first line of the release notes does not contain a semantic version, please "
                             "check this.")
        self.assertEqual(first_version_in_release_notes, version.version,
                         "Version in release notes is not equal to setup version")


if __name__ == '__main__':
    unittest.main()
