#!/usr/bin/env python3
"""Flag top-level DAB bundles not referenced in common CI path lists.

Usage: check_ci_bundle_paths.py /path/to/clone [--pipeline path]

Stdlib only. Compares directories containing databricks.yml at repo root (one
level deep) against path prefixes extracted from bitbucket-pipelines.yml or ADO YAML.
"""

from __future__ import annotations

import argparse
import re
import sys
from pathlib import Path

BUNDLE_GLOB = "databricks.yml"
PATH_QUOTED = re.compile(r'["\']([A-Za-z0-9_./-]+)/\*\*["\']')
PATH_BARE = re.compile(r"^\s+-\s+([A-Za-z0-9_]+)/")


def top_level_bundles(root: Path) -> set[str]:
    names: set[str] = set()
    for yml in root.glob("*/databricks.yml"):
        if yml.parent.is_dir():
            names.add(yml.parent.name)
    return names


def ci_path_prefixes(pipeline_file: Path) -> set[str]:
    text = pipeline_file.read_text(encoding="utf-8", errors="replace")
    prefixes: set[str] = set()
    for m in PATH_QUOTED.finditer(text):
        p = m.group(1).strip("/")
        if p and "/" not in p:
            prefixes.add(p.split("/")[0])
    for line in text.splitlines():
        m = PATH_BARE.match(line)
        if m:
            prefixes.add(m.group(1))
    # shell comparisons like bundle = "pricing"
    for m in re.finditer(r'\[ "\$bundle" = "([^"]+)" \]', text):
        prefixes.add(m.group(1))
    return prefixes


def find_default_pipeline(root: Path) -> Path | None:
    candidates = [
        root / "bitbucket-pipelines.yml",
        root / "YAML Pipelines" / "build-pipeline-adb.yml",
    ]
    for c in candidates:
        if c.is_file():
            return c
    return None


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("clone", type=Path, help="Path to target repo clone")
    parser.add_argument("--pipeline", type=Path, help="CI YAML (default: auto-detect)")
    args = parser.parse_args()
    root = args.clone.resolve()
    if not root.is_dir():
        print(f"Not a directory: {root}", file=sys.stderr)
        return 2

    bundles = top_level_bundles(root)
    if not bundles:
        print("No top-level */databricks.yml bundles found.")
        return 0

    pipeline = args.pipeline or find_default_pipeline(root)
    if pipeline is None or not pipeline.is_file():
        print("No pipeline file found; listing bundles only:")
        print(" ", ", ".join(sorted(bundles)))
        return 0

    prefixes = ci_path_prefixes(pipeline)
    uncovered = sorted(b for b in bundles if b not in prefixes)
    covered = sorted(b for b in bundles if b in prefixes)

    print(f"Pipeline: {pipeline}")
    print(f"Bundles ({len(bundles)}): {', '.join(sorted(bundles))}")
    print(f"CI path prefixes ({len(prefixes)}): {', '.join(sorted(prefixes)) or '(none parsed)'}")
    if uncovered:
        print("Possibly uncovered by CI paths:")
        for name in uncovered:
            print(f"  - {name}")
        return 1
    print("All bundles appear in at least one CI path rule.")
    return 0


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