#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
cd "$REPO_ROOT"

TARGET="${1:-}"

# Dynamically discover packages and methodologies via parts/autofab.toml (or cleanroom.toml)
DISCOVERED_PATHS="$(python3 -c '
import os, tomllib
from pathlib import Path

repo_root = Path(".").resolve()
pypaths = [str(repo_root)]
seen_meth = set()

for entry in sorted(repo_root.iterdir()):
    if entry.is_dir() and not entry.name.startswith((".", "bazel", "venv", "staging", "node_modules", "build", "dist")):
        parts_cfg = None
        for cand_name in ("autofab.toml", "cleanroom.toml"):
            cand = entry / "parts" / cand_name
            if cand.is_file():
                parts_cfg = cand
                break
        if parts_cfg:
            if not (entry / "__init__.py").is_file():
                pypaths.append(str(entry))
            sup = entry / "support" / "lib"
            if sup.is_dir():
                pypaths.append(str(sup))
            try:
                data = tomllib.loads(parts_cfg.read_text(encoding="utf-8"))
                meth = data.get("methodology", "").lstrip("./").lstrip("/")
                if meth and meth not in seen_meth:
                    seen_meth.add(meth)
                    meth_dir = repo_root / meth
                    if meth_dir.is_dir():
                        pypaths.append(str(meth_dir))
                        meth_sup = meth_dir / "support" / "lib"
                        if meth_sup.is_dir():
                            pypaths.append(str(meth_sup))
            except Exception:
                pass

print(":".join(pypaths))
')"

PYPATHS=()
IFS=: read -ra PYPATHS <<< "$DISCOVERED_PATHS"

if [ -n "$TARGET" ] && [ -d "$REPO_ROOT/$TARGET" ]; then
    if [ ! -f "$REPO_ROOT/$TARGET/__init__.py" ]; then
        PYPATHS+=("$REPO_ROOT/$TARGET")
    fi
    TARGET_PARENT="$(dirname "$REPO_ROOT/$TARGET")"
    if [ -d "$TARGET_PARENT" ]; then
        PYPATHS+=("$TARGET_PARENT")
        TARGET_GRANDPARENT="$(dirname "$TARGET_PARENT")"
        if [ -d "$TARGET_GRANDPARENT" ]; then
            PYPATHS+=("$TARGET_GRANDPARENT")
        fi
    fi
    for sub in "$REPO_ROOT/$TARGET"/lib "$REPO_ROOT/$TARGET"/low "$REPO_ROOT/$TARGET"/tests "$REPO_ROOT/$TARGET"/pretense; do
        if [ -d "$sub" ]; then
            PYPATHS+=("$sub")
        fi
    done
fi

export PYTHONPATH="$(IFS=:; echo "${PYPATHS[*]}"):${PYTHONPATH:-}"

# Execute specification linters dynamically based on parts/autofab.toml and autofab_roles.toml
python3 -c '
import os, sys, tomllib, subprocess
from pathlib import Path

repo_root = Path(".").resolve()
target_arg = sys.argv[1] if len(sys.argv) > 1 else ""

def find_parts_config_toml(p: Path) -> Path | None:
    for fname in ("autofab.toml", "cleanroom.toml"):
        cand = p / "parts" / fname
        if cand.is_file():
            return cand
    curr = p if p.is_dir() else p.parent
    while curr != curr.parent and curr != repo_root.parent:
        if curr.name == "parts":
            for fname in ("autofab.toml", "cleanroom.toml"):
                cand = curr / fname
                if cand.is_file():
                    return cand
        for fname in ("autofab.toml", "cleanroom.toml"):
            cand = curr / "parts" / fname
            if cand.is_file():
                return cand
        curr = curr.parent
    return None

def get_installed_roles(cfg_path: Path) -> tuple[str, dict]:
    try:
        data = tomllib.loads(cfg_path.read_text(encoding="utf-8"))
        meth = data.get("methodology", "").lstrip("./").lstrip("/")
        if not meth:
            return "", {}
        roles_cfg = None
        for rname in ("autofab_roles.toml", "cleanroom_roles.toml"):
            cand = repo_root / meth / rname
            if cand.is_file():
                roles_cfg = cand
                break
        if not roles_cfg:
            return meth, {}
        roles_data = tomllib.loads(roles_cfg.read_text(encoding="utf-8"))
        return meth, roles_data.get("roles", {})
    except Exception:
        return "", {}

def run_role_linters(target_path_str: str, parts_cfg: Path):
    meth, roles = get_installed_roles(parts_cfg)
    if "spec_qa" not in roles and "high" not in roles:
        return
    spec_qa_tools = roles.get("spec_qa", {}).get("tools", [])
    high_tool = next((t for t in spec_qa_tools if t.endswith("high_lint")), None)
    spec_tool = next((t for t in spec_qa_tools if t.endswith("spec_lint")), None)
    low_tool = next((t for t in spec_qa_tools if t.endswith("low_lint")), None)

    label = target_path_str if target_path_str else "repo-wide"
    print(f"=== Specification Linters ({meth}): {label} ===")
    if target_path_str.endswith(".md") and "/high/" in target_path_str:
        if high_tool:
            subprocess.run(["uv", "run", "python", "-m", high_tool, target_path_str], check=True)
    elif target_path_str.endswith(".md") and "/planning/" in target_path_str:
        if spec_tool:
            subprocess.run(["uv", "run", "python", "-m", spec_tool, target_path_str], check=True)
    elif target_path_str.endswith(".pyi") and "/low/" in target_path_str:
        if low_tool:
            subprocess.run(["uv", "run", "python", "-m", low_tool, target_path_str], check=True)
    elif not target_path_str or (repo_root / target_path_str).is_dir():
        cmd_arg = [target_path_str] if target_path_str else []
        if high_tool:
            subprocess.run(["uv", "run", "python", "-m", high_tool] + cmd_arg, check=True)
        if spec_tool:
            subprocess.run(["uv", "run", "python", "-m", spec_tool] + cmd_arg, check=True)
        if low_tool:
            subprocess.run(["uv", "run", "python", "-m", low_tool] + cmd_arg, check=True)
    print("")

if target_arg and not target_arg.startswith("-"):
    t_path = (repo_root / target_arg).resolve()
    cfg = find_parts_config_toml(t_path)
    if cfg:
        run_role_linters(target_arg, cfg)
else:
    for entry in sorted(repo_root.iterdir()):
        if entry.is_dir() and not entry.name.startswith((".", "bazel", "venv", "staging", "node_modules", "build", "dist")):
            for fname in ("autofab.toml", "cleanroom.toml"):
                cfg = entry / "parts" / fname
                if cfg.is_file():
                    run_role_linters(str(entry.relative_to(repo_root)), cfg)
                    break
' "${TARGET:-}"

if [ -n "$TARGET" ] && [ "${TARGET:0:1}" != "-" ]; then
    case "$TARGET" in
        *.md)
            exit 0
            ;;
        *.pyi)
            echo "=== Type Checking Specification Stub: $TARGET ==="
            SPEC_PROJ="autofab_python/pyright_spec.json"
            if [ ! -f "$SPEC_PROJ" ]; then
                SPEC_PROJ="update_python_with_ai/pyright_spec.json"
            fi
            uv run pyright --project "$SPEC_PROJ" "$TARGET"
            exit 0
            ;;
        *_pretense.py)
            echo "=== Type Checking: $TARGET ==="
            uv run pyright "$TARGET"
            echo ""
            echo "=== Pretense Tests: $TARGET ==="
            exec uv run pretense "$TARGET"
            ;;
        *)
            echo "=== Type Checking: $TARGET ==="
            CHECK_TARGETS=()
            if [ -d "$TARGET" ]; then
                for sub in lib tests pretense; do
                    if [ -d "$TARGET/$sub" ]; then
                        CHECK_TARGETS+=("$TARGET/$sub")
                    fi
                done
            fi
            if [ "${#CHECK_TARGETS[@]}" -gt 0 ]; then
                uv run pyright "${CHECK_TARGETS[@]}"
            else
                uv run pyright "$TARGET"
            fi
            echo ""
            echo "=== Tests: $TARGET ==="
            shift || true
            PYTEST_EXIT=0
            if [ -d "$TARGET/tests" ] || find "$TARGET" -name "*_test.py" -print -quit 2>/dev/null | grep -q .; then
                uv run pytest -q --tb=short "$TARGET" "$@" || PYTEST_EXIT=$?
                if [ "$PYTEST_EXIT" -ne 0 ] && [ "$PYTEST_EXIT" -ne 5 ]; then
                    exit "$PYTEST_EXIT"
                fi
            fi
            if [ -d "$TARGET/pretense" ] || find "$TARGET" -name "*_pretense.py" -print -quit 2>/dev/null | grep -q .; then
                echo ""
                echo "=== Pretense Tests: $TARGET ==="
                uv run pretense "$TARGET"
            fi
            ;;
    esac
else
    echo "=== Type Checking (pyright) ==="
    uv run pyright autofab autofab_python pretense
    echo ""
    echo "=== Tests (pytest) ==="
    uv run pytest -q --tb=short "$@"
    echo ""
    echo "=== Pretense Tests ==="
    uv run pretense autofab/parts/ pretense/parts/
fi
