#!/usr/bin/python3

"""Update modules.d rules in .github/labeler.py."""

import argparse
import difflib
import os
import pathlib
import re
import sys


def generate_diff(before: str, after: str, filename: str) -> str:
    """Generate a unified diff between the two given file contents."""
    before_lines = before.splitlines(keepends=True)
    after_lines = after.splitlines(keepends=True)
    diff = difflib.unified_diff(
        before_lines, after_lines, fromfile=f"a/{filename}", tofile=f"b/{filename}"
    )
    return "".join(diff)


def generate_labeler_yaml(modules: list[str], header: str) -> str:
    """Generate a labeler YAML file from the given list of Dracut modules."""
    script_name = pathlib.Path(__file__).relative_to(os.getcwd())
    comment = f"# The following lines were generated by {script_name}\n"
    return header + comment + "\n".join(f"""\
{module}:
    - changed-files:
          - any-glob-to-any-file: 'modules.d/[0-9][0-9]{module}/*'
""" for module in modules)


def get_modules_names(modules_dir: pathlib.Path) -> list[str]:
    """List module names (without their numbers) in the given modules.d directory."""
    return sorted(
        x.name[2:] for x in modules_dir.iterdir() if x.is_dir() and not x.is_symlink()
    )


def remove_generated_part(yaml_content: str) -> str:
    """Remove the part of the labeler YAML that was generated by this script."""
    return re.sub(
        "# The following lines were generated.*$", "", yaml_content, flags=re.DOTALL
    )


def main() -> int:
    """Update modules.d rules in .github/labeler.py."""
    parser = argparse.ArgumentParser()
    parser.add_argument("-c", "--check", action="store_true")
    parser.add_argument("--labeler", default=".github/labeler.yml")
    args = parser.parse_args()

    modules = get_modules_names(pathlib.Path("modules.d"))
    current_labeler_yaml = pathlib.Path(args.labeler).read_text("utf-8")
    header = remove_generated_part(current_labeler_yaml)
    new_labeler_yaml = generate_labeler_yaml(modules, header)
    diff = generate_diff(current_labeler_yaml, new_labeler_yaml, args.labeler)
    if not diff:
        return 0

    if args.check:
        print(diff, end="")
        return 1

    pathlib.Path(args.labeler).write_text(new_labeler_yaml, "utf-8")
    return 0


if __name__ == "__main__":
    sys.exit(main())
