"""Pre-flight brief for /build — surfaces recipes, pitfalls, and project files."""

import json
import re
import sys
from pathlib import Path


def _find_project_root() -> Path | None:
    """Walk up from cwd to find a Godot project root (has project.godot)."""
    cwd = Path.cwd()
    for parent in [cwd, *cwd.parents]:
        if (parent / "project.godot").exists():
            return parent
    return None


def _parse_recipes_index(recipes_index: Path) -> list[dict]:
    """Parse recipes/INDEX.md and return list of {file, keywords}."""
    if not recipes_index.exists():
        return []

    entries = []
    for line in recipes_index.read_text(encoding="utf-8").splitlines():
        # Match table rows: | Concept | `filename.md` | keyword1, keyword2, ... |
        m = re.match(r"\|\s*(.+?)\s*\|\s*`(.+?)`\s*\|\s*(.+?)\s*\|", line)
        if m and not m.group(1).startswith("---") and m.group(1).strip() != "Concept":
            concept = m.group(1).strip()
            filename = m.group(2).strip()
            keywords = [k.strip().lower() for k in m.group(3).split(",")]
            entries.append({
                "concept": concept,
                "file": filename,
                "keywords": keywords,
            })
    return entries


def _match_recipes(entries: list[dict], task_words: set[str]) -> list[dict]:
    """Return recipes whose keywords overlap with the task words."""
    matched = []
    for entry in entries:
        hits = [kw for kw in entry["keywords"] if kw in task_words]
        if hits:
            matched.append({
                "file": entry["file"],
                "concepts": hits,
            })
    return matched


def _parse_pitfalls(pitfalls_path: Path) -> list[dict]:
    """Parse references/gdscript_pitfalls.md — extract section headings and first-line summaries."""
    if not pitfalls_path.exists():
        return []

    sections = []
    current_heading = None

    for line in pitfalls_path.read_text(encoding="utf-8").splitlines():
        # Match ## N. Title or ## Title
        m = re.match(r"^##\s+(?:\d+\.\s+)?(.+)", line)
        if m:
            current_heading = m.group(1).strip()
            continue

        # Grab ### Symptôme or first paragraph line after heading
        if current_heading and line.strip() and not line.startswith("#"):
            # Skip markdown formatting lines
            if line.startswith("---") or line.startswith(">") or line.startswith("|"):
                if line.startswith(">"):
                    continue
                if line.startswith("---"):
                    current_heading = None
                    continue
                continue
            sections.append({
                "heading": current_heading,
                "summary": line.strip()[:120],
                "keywords": set(re.findall(r"[a-z_]+", current_heading.lower())),
            })
            current_heading = None

    return sections


def _match_pitfalls(sections: list[dict], task_words: set[str]) -> list[str]:
    """Return pitfall summaries where heading keywords overlap with task words."""
    matched = []
    for section in sections:
        if section["keywords"] & task_words:
            matched.append(f"{section['heading']} — {section['summary']}")
    return matched


def _scan_project_files(project_root: Path, task_words: set[str]) -> list[str]:
    """Scan *.gd, *.tscn, *.tres for filenames/content matching task keywords."""
    matched = []
    extensions = {".gd", ".tscn", ".tres"}

    for ext in extensions:
        for filepath in project_root.rglob(f"*{ext}"):
            # Skip addons
            rel = filepath.relative_to(project_root)
            if str(rel).startswith("addons") or str(rel).startswith("."):
                continue

            # Match on filename
            name_words = set(re.findall(r"[a-z]+", filepath.stem.lower()))
            if name_words & task_words:
                matched.append(f"res://{rel.as_posix()}")
                continue

            # Match on content (first 2000 chars for speed)
            try:
                content = filepath.read_text(encoding="utf-8", errors="ignore")[:2000].lower()
                content_words = set(re.findall(r"[a-z_]+", content))
                if len(task_words & content_words) >= 2:
                    matched.append(f"res://{rel.as_posix()}")
            except OSError:
                continue

    return sorted(set(matched))[:20]  # Cap at 20 files


def _tokenize_task(task: str) -> set[str]:
    """Split task description into lowercase keyword tokens."""
    # Split on spaces, punctuation
    words = set(re.findall(r"[a-z]+", task.lower()))
    # Remove common stop words
    stop_words = {
        "a", "an", "the", "is", "are", "was", "were", "be", "been",
        "do", "does", "did", "have", "has", "had", "will", "would",
        "can", "could", "should", "may", "might", "must", "shall",
        "to", "of", "in", "for", "on", "with", "at", "by", "from",
        "and", "or", "but", "not", "no", "if", "then", "else",
        "this", "that", "it", "its", "my", "your", "our", "their",
        "un", "une", "le", "la", "les", "de", "du", "des", "et",
        "qui", "que", "dans", "pour", "avec", "sur", "par",
        "je", "tu", "il", "nous", "vous", "ils",
        "add", "create", "make", "implement", "ajoute", "cree", "fait",
    }
    return words - stop_words


def main() -> None:
    if len(sys.argv) < 2:
        print(json.dumps({"error": "Usage: preflight.py \"task description\""}))
        sys.exit(1)

    task = " ".join(sys.argv[1:])
    task_words = _tokenize_task(task)

    if not task_words:
        print(json.dumps({"recipes": [], "pitfalls": [], "files": []}))
        return

    project_root = _find_project_root()

    # Locate data files — try .claude/ paths first (installed), then repo-relative
    recipes_index = None
    pitfalls_path = None

    search_bases = []
    if project_root:
        search_bases.append(project_root)
    search_bases.append(Path.cwd())

    for base in search_bases:
        if not recipes_index:
            candidate = base / "recipes" / "INDEX.md"
            if candidate.exists():
                recipes_index = candidate
        if not pitfalls_path:
            candidate = base / "references" / "gdscript_pitfalls.md"
            if candidate.exists():
                pitfalls_path = candidate

    # Parse and match
    recipes = []
    if recipes_index:
        entries = _parse_recipes_index(recipes_index)
        recipes = _match_recipes(entries, task_words)

    pitfalls = []
    if pitfalls_path:
        sections = _parse_pitfalls(pitfalls_path)
        pitfalls = _match_pitfalls(sections, task_words)

    files = []
    if project_root:
        files = _scan_project_files(project_root, task_words)

    result = {
        "recipes": recipes,
        "pitfalls": pitfalls,
        "files": files,
    }

    print(json.dumps(result, indent=2, ensure_ascii=False))


if __name__ == "__main__":
    main()
