#! /usr/bin/env python3

from pathlib import Path
import argparse

def parse_args():
    parser = argparse.ArgumentParser(description="Count and sort lines of code in selected files.")
    parser.add_argument(
        "--search-dirs", nargs="+", required=True,
        help="List of directories to search (recursively)."
    )
    parser.add_argument(
        "--include-exts", nargs="+", required=True,
        help="List of file extensions to include (e.g. .cpp .hpp .py)"
    )
    parser.add_argument(
        "--exclude-paths", nargs="*", default=[],
        help="Full file paths to exclude from counting."
    )
    return parser.parse_args()


def main():
    args = parse_args()
    include_exts = tuple(args.include_exts)
    exclude_paths = {Path(p).resolve() for p in args.exclude_paths}
    files = []
    for base in args.search_dirs:
        path = Path(base)
        if path.is_dir():
            for file in path.rglob("*"):
                try:
                    resolved_file = file.resolve()
                    if (
                        file.is_file()
                        and file.name.endswith(include_exts)
                        and resolved_file not in exclude_paths
                    ):
                        files.append(str(resolved_file))
                except FileNotFoundError:
                    continue
    line_counts = []
    total_lines = 0
    for f in files:
        try:
            with open(f, "r", encoding="utf-8", errors="ignore") as file:
                lines = sum(1 for _ in file)
            line_counts.append((lines, f))
            total_lines += lines
        except Exception as e:
            print(f"Failed to read {f}: {e}")
    line_counts.sort()
    for count, filename in line_counts:
        print(f"{count:>7} {filename}")
    print(f"{total_lines:>7} total")


if __name__ == "__main__":
    main()
