#!/usr/bin/env bash
#
# Package the Businessmap Code Runner skill for distribution.
#
# Produces build/businessmap-code-runner.zip with the skill folder at the zip
# root, which is what the claude.ai upload requires — a zip with files loose at
# the root is rejected. The same folder can also be copied straight into
# ~/.claude/skills/ for Claude Code.
#
# Usage: bash scripts/build-skill.sh
#
set -euo pipefail

SKILL_NAME="businessmap-code-runner"
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SRC="$ROOT/skills/$SKILL_NAME"
OUT_DIR="$ROOT/build"
OUT="$OUT_DIR/$SKILL_NAME.zip"

fail() { printf 'build-skill: %s\n' "$1" >&2; exit 1; }

[ -d "$SRC" ]            || fail "no skill directory at $SRC"
[ -f "$SRC/SKILL.md" ]   || fail "no SKILL.md in $SRC"
command -v zip >/dev/null || fail "the 'zip' command is required"

# --- validate the frontmatter before shipping it -----------------------------
# name:        <= 64 chars, lowercase/digits/hyphen, no reserved words
# description: <= 200 chars (the claude.ai limit; the API allows 1024, but the
#              smaller of the two is the one that has to hold)
python3 - "$SRC/SKILL.md" "$SKILL_NAME" <<'PY'
import re, sys

path, expected = sys.argv[1], sys.argv[2]
text = open(path, encoding="utf-8").read()

match = re.match(r"^---\n(.*?)\n---\n", text, re.S)
if not match:
    sys.exit("build-skill: SKILL.md has no YAML frontmatter")
block = match.group(1)

def field(key):
    found = re.search(rf"^{key}:\s*(.+?)\s*$", block, re.M)
    return found.group(1) if found else None

name, description = field("name"), field("description")
errors = []

if not name:
    errors.append("frontmatter is missing 'name'")
else:
    if not re.fullmatch(r"[a-z0-9-]{1,64}", name):
        errors.append(f"name {name!r} must be 1-64 chars of [a-z0-9-]")
    for reserved in ("anthropic", "claude"):
        if reserved in name.lower():
            errors.append(f"name may not contain the reserved word {reserved!r}")
    if name != expected:
        errors.append(f"name {name!r} must match the folder name {expected!r}")

if not description:
    errors.append("frontmatter is missing 'description'")
elif len(description) > 200:
    errors.append(f"description is {len(description)} chars; the claude.ai limit is 200")

if "<" in block and ">" in block:
    errors.append("frontmatter may not contain XML tags")

if errors:
    sys.exit("build-skill: " + "\n           ".join(errors))

print(f"  name:        {name}")
print(f"  description: {len(description)}/200 chars")
PY

# --- syntax-check every bundled helper ---------------------------------------
shopt -s nullglob
for helper in "$SRC"/scripts/*.py; do
	python3 -m py_compile "$helper" || fail "$(basename "$helper") does not compile"
done
shopt -u nullglob
rm -rf "$SRC/scripts/__pycache__"

# --- package -----------------------------------------------------------------
mkdir -p "$OUT_DIR"
rm -f "$OUT"

# Zip from the parent so every entry is prefixed with the skill folder name.
( cd "$ROOT/skills" && zip -r -q "$OUT" "$SKILL_NAME" \
	-x '*/__pycache__/*' '*/.DS_Store' '*.pyc' )

printf '\n  wrote %s (%s)\n\n' "${OUT#"$ROOT"/}" "$(du -h "$OUT" | cut -f1)"
unzip -l "$OUT" | sed 's/^/  /'
