import re
from pathlib import Path
import sys
import _colorize
import textwrap

SIMPLE_FUNCTION_REGEX = re.compile(r"PyAPI_FUNC(.+) (\w+)\(")
SIMPLE_MACRO_REGEX = re.compile(r"# *define *(\w+)(\(.+\))? ")
SIMPLE_INLINE_REGEX = re.compile(r"static inline .+( |\n)(\w+)")
SIMPLE_DATA_REGEX = re.compile(r"PyAPI_DATA\(.+\) (\w+)")
API_NAME_REGEX = re.compile(r'\bP[yY][a-zA-Z0-9_]+')

CPYTHON = Path(__file__).parent.parent.parent
INCLUDE = CPYTHON / "Include"
C_API_DOCS = CPYTHON / "Doc" / "c-api"
IGNORED = (
    (CPYTHON / "Tools" / "check-c-api-docs" / "ignored_c_api.txt")
    .read_text()
    .split("\n")
)

for index, line in enumerate(IGNORED):
    if line.startswith("#"):
        IGNORED.pop(index)

MISTAKE = """
If this is a mistake and this script should not be failing, create an
issue and tag Peter (@ZeroIntensity) on it.\
"""


def found_undocumented(singular: bool) -> str:
    some = "an" if singular else "some"
    s = "" if singular else "s"
    these = "this" if singular else "these"
    them = "it" if singular else "them"
    were = "was" if singular else "were"

    return (
        textwrap.dedent(
            f"""
    Found {some} undocumented C API{s}!

    Python requires documentation on all public C API symbols, macros, and types.
    If {these} API{s} {were} not meant to be public, prefix {them} with a
    leading underscore (_PySomething_API) or move {them} to the internal C API
    (pycore_*.h files).

    In exceptional cases, certain APIs can be ignored by adding them to
    Tools/check-c-api-docs/ignored_c_api.txt
    """
        )
        + MISTAKE
    )


def found_ignored_documented(singular: bool) -> str:
    some = "a" if singular else "some"
    s = "" if singular else "s"
    them = "it" if singular else "them"
    were = "was" if singular else "were"
    they = "it" if singular else "they"

    return (
        textwrap.dedent(
            f"""
    Found {some} C API{s} listed in Tools/c-api-docs-check/ignored_c_api.txt, but
    {they} {were} found in the documentation. To fix this, remove {them} from
    ignored_c_api.txt.
    """
        )
        + MISTAKE
    )


def scan_file_for_docs(
    filename: str,
    text: str,
    names: set[str]) -> tuple[list[str], list[str]]:
    """
    Scan a header file for  C API functions.
    """
    undocumented: list[str] = []
    documented_ignored: list[str] = []
    colors = _colorize.get_colors()

    def check_for_name(name: str) -> None:
        documented = name in names
        if documented and (name in IGNORED):
            documented_ignored.append(name)
        elif not documented and (name not in IGNORED):
            undocumented.append(name)

    for function in SIMPLE_FUNCTION_REGEX.finditer(text):
        name = function.group(2)
        if not API_NAME_REGEX.fullmatch(name):
            continue

        check_for_name(name)

    for macro in SIMPLE_MACRO_REGEX.finditer(text):
        name = macro.group(1)
        if not API_NAME_REGEX.fullmatch(name):
            continue

        if "(" in name:
            name = name[: name.index("(")]

        check_for_name(name)

    for inline in SIMPLE_INLINE_REGEX.finditer(text):
        name = inline.group(2)
        if not API_NAME_REGEX.fullmatch(name):
            continue

        check_for_name(name)

    for data in SIMPLE_DATA_REGEX.finditer(text):
        name = data.group(1)
        if not API_NAME_REGEX.fullmatch(name):
            continue

        check_for_name(name)

    # Remove duplicates and sort alphabetically to keep the output deterministic
    undocumented = list(set(undocumented))
    undocumented.sort()

    if undocumented or documented_ignored:
        print(f"{filename} {colors.RED}BAD{colors.RESET}")
        for name in undocumented:
            print(f"{colors.BOLD_RED}UNDOCUMENTED:{colors.RESET} {name}")
        for name in documented_ignored:
            print(f"{colors.BOLD_YELLOW}DOCUMENTED BUT IGNORED:{colors.RESET} {name}")
    else:
        print(f"{filename} {colors.GREEN}OK{colors.RESET}")

    return undocumented, documented_ignored


def main() -> None:
    print("Gathering C API names from docs...")
    names = set()
    for path in C_API_DOCS.glob('**/*.rst'):
        text = path.read_text(encoding="utf-8")
        for name in API_NAME_REGEX.findall(text):
            names.add(name)
    print(f"Got {len(names)} names!")

    print("Scanning for undocumented C API functions...")
    files = [*INCLUDE.iterdir(), *(INCLUDE / "cpython").iterdir()]
    all_missing: list[str] = []
    all_found_ignored: list[str] = []

    for file in files:
        if file.is_dir():
            continue
        assert file.exists()
        text = file.read_text(encoding="utf-8")
        missing, ignored = scan_file_for_docs(str(file.relative_to(INCLUDE)), text, names)
        all_found_ignored += ignored
        all_missing += missing

    fail = False
    to_check = [
        (all_missing, "missing", found_undocumented(len(all_missing) == 1)),
        (
            all_found_ignored,
            "documented but ignored",
            found_ignored_documented(len(all_found_ignored) == 1),
        ),
    ]
    for name_list, what, message in to_check:
        if not name_list:
            continue

        s = "s" if len(name_list) != 1 else ""
        print(f"-- {len(name_list)} {what} C API{s} --")
        for name in name_list:
            print(f" - {name}")
        print(message)
        fail = True

    sys.exit(1 if fail else 0)


if __name__ == "__main__":
    main()
