import re
from pathlib import Path

import sphinxlint


REDIRECT_RULE_RE = re.compile(r'^[ \t]*([\w\-/]+\.rst)[ \t]+([\w\-/]+\.rst)[ \t]*(?:#.*)?$')
REDIRECTS_FILE_VERSION_RE = re.compile(r'(?:redirects/)?(?:saas-)?(\d\d\.\d)\.txt')


@sphinxlint.checker('.txt')
def check_redirect_rules_format(file, lines, options=None):
    """ Check that redirect rules are correctly formatted. """
    if file.startswith('redirects/'):  # Only check text files in the /redirects folder.
        for lno, line in enumerate(lines):
            if not line.rstrip() or line.startswith('#'):
                continue
            if not REDIRECT_RULE_RE.search(line):
                yield lno + 1, "invalid redirect rule format; learn more at redirects/MANUAL.md"


@sphinxlint.checker('.txt')
def check_redirect_rules_target(file, lines, options=None):
    """ Check that redirect rules refer to existing files. """
    def get_redirects_file_version(file_name_):
        match_ = REDIRECTS_FILE_VERSION_RE.search(file_name_)
        if match_:
            return float(match_.group(1))
        return -1.0

    if file.startswith('redirects/'):  # Only check text files in the /redirects folder.
        # Find the current version, which is that of the file with the latest version.
        redirects_dir = Path('redirects')
        latest_redirects_version = 0.0
        for redirect_file in redirects_dir.iterdir():
            if redirect_file.is_dir() or redirect_file.suffix != '.txt':
                continue
            latest_redirects_version = max(
                latest_redirects_version, get_redirects_file_version(redirect_file.name)
            )

        # Only check the existence of the redirection target if we are in the right version.
        current_file_version = get_redirects_file_version(file)
        if current_file_version < latest_redirects_version:
            return

        for lno, line in enumerate(lines):
            if not line.rstrip() or line.startswith('#'):
                continue
            match_res = REDIRECT_RULE_RE.search(line)
            if match_res:
                _old_path, new_path = match_res.groups()
                redirect_file = Path('content') / new_path
                if not redirect_file.is_file():
                    yield lno + 1, f"the redirect rule targets the non-existing file {new_path}"