"""H-15: backfill missing boolean flag keys in registry layer files.

Every registry entry must declare all 8 flag keys per the ToolFlags
schema.  Layer files that pre-date the schema expansion only declare
the first three (has_cli / has_gui / has_web).  This script appends the
missing five (is_ollama / is_docker / is_passive / is_mcp /
is_skills_collection) defaulting to ``False`` to every flags block in
every layer file under ``registry/layers/``.
"""

from __future__ import annotations

import re
import sys
from pathlib import Path

LAYER_DIR = Path("/home/z/my-project/workspace/ai-lsc/src/ai_lsc/registry/layers")
REQUIRED_KEYS = [
    "has_cli",
    "has_gui",
    "has_web",
    "is_ollama",
    "is_docker",
    "is_passive",
    "is_mcp",
    "is_skills_collection",
]

# Matches a `"flags": { ... }` block, capturing the inner body.
_FLAGS_RE = re.compile(
    r'("flags":\s*\{)([^}]*)(\})',
    re.DOTALL,
)


def backfill(text: str) -> tuple[str, int]:
    """Return (new_text, number_of_blocks_updated)."""
    updated = 0

    def repl(m: re.Match) -> str:
        nonlocal updated
        head, body, tail = m.group(1), m.group(2), m.group(3)
        present = set(re.findall(r'"([a-z_]+)"\s*:', body))
        missing = [k for k in REQUIRED_KEYS if k not in present]
        if not missing:
            return m.group(0)
        indent_match = re.search(r'\n([ \t]+)"', body)
        indent = indent_match.group(1) if indent_match else "        "
        # Build the new body from scratch.  Strip trailing whitespace
        # and any trailing comma from the existing body so we can append
        # new lines cleanly; if the body is empty (was `{}`), start fresh.
        body_stripped = body.rstrip()
        body_stripped = re.sub(r',\s*$', '', body_stripped)
        new_lines = []
        if body_stripped:
            new_lines.append(body_stripped + ",")
        for i, k in enumerate(missing):
            suffix = "," if i < len(missing) - 1 else ""
            new_lines.append(f'{indent}"{k}": False{suffix}')
        updated += 1
        close_indent = indent[:-4] if len(indent) >= 4 else ""
        return f"{head}" + "\n".join(new_lines) + f"\n{close_indent}{tail}"

    new_text = _FLAGS_RE.sub(repl, text)
    return new_text, updated


def main() -> int:
    if not LAYER_DIR.is_dir():
        print(f"layer dir not found: {LAYER_DIR}", file=sys.stderr)
        return 2
    total_blocks = 0
    total_files = 0
    for path in sorted(LAYER_DIR.glob("*.py")):
        original = path.read_text(encoding="utf-8")
        new_text, blocks = backfill(original)
        if blocks:
            path.write_text(new_text, encoding="utf-8")
            print(f"  {path.name}: updated {blocks} flags block(s)")
            total_blocks += blocks
            total_files += 1
        else:
            print(f"  {path.name}: no changes needed")
    print(f"\nUpdated {total_blocks} flags block(s) across {total_files} file(s).")
    return 0


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