from __future__ import annotations

import argparse
import sys
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parents[1]
SKILLS_DIR = REPO_ROOT / "skills"
DOCS_DIR = REPO_ROOT / "docs"
SNIPPETS_DIR = DOCS_DIR / "snippets"

GLOBAL_CARD = SKILLS_DIR / "agent-memory-skill.global.md"
READONLY_CARD = SKILLS_DIR / "agent-memory-skill.readonly.md"

HEADER = "<!-- AUTO-GENERATED by scripts/generate_agent_memory_skill_assets.py. Do not edit directly. -->"


def _read(path: Path) -> str:
    return path.read_text(encoding="utf-8").rstrip() + "\n"


def _render_cards_doc(global_card: str, readonly_card: str) -> str:
    return f"""{HEADER}
# Agent memory skill cards (global default + read-only carve-out)

These are the **drop-in, one-screen** prompt/skill snippets.

Canonical copies live in repo root:
- `skills/agent-memory-skill.global.md`
- `skills/agent-memory-skill.readonly.md`

## 1) Global default card

```md
{global_card.rstrip()}
```

## 2) Read-only carve-out card

```md
{readonly_card.rstrip()}
```

## Prompt wiring templates (OpenClaw)

If you want this to be copy/paste deployable on real prompt surfaces:

- Default agent/system prompt add-on (global): `docs/snippets/openclaw-agentturn-message.global-default.md`
- Cron watchdog/healthcheck `agentTurn` message (read-only): `docs/snippets/openclaw-agentturn-message.watchdog-readonly.md`

For JSON configs, use `scripts/json_escape.py` to embed multi-line messages (see [Deployment](deployment.md)).
"""


def _render_global_snippet(global_card: str) -> str:
    return f"""{HEADER}
# Agent memory skill — global default (prompt add-on)

Paste this into your **default agent/system prompt** (or skills library) for any agent that can call:
- `memory_recall` / `memory_store`
- `memory_docs_search`

---

## Skill card (global default)

Canonical source: `skills/agent-memory-skill.global.md`.

{global_card.rstrip()}
"""


def _render_readonly_snippet(readonly_card: str) -> str:
    return f"""{HEADER}
# OpenClaw `agentTurn` message template — watchdog/healthcheck (READ-ONLY)

Use this as the `payload.message` for cron lanes like watchdog / healthcheck / lint / smoke.

Contract:
- ✅ You may use: `memory_recall`, `memory_docs_search`, topology inspection.
- 🚫 Do **not** call `memory_store` in this lane.
- If everything is OK: output **ONLY** `NO_REPLY`.
- If anomaly: output a concise alert (what broke + why it matters + next action).

---

## Skill card (read-only carve-out)

Canonical source: `skills/agent-memory-skill.readonly.md`.

{readonly_card.rstrip()}

---

## Task instructions (watchdog lane)

1) Run **exactly one** `exec` (or the minimal commands needed) to perform the healthcheck.
2) Optionally use `memory_recall` / `memory_docs_search` to interpret thresholds / "normal" baselines.
3) Decision:
   - If OK: output **ONLY** `NO_REPLY`.
   - If anomaly: output a short incident summary + recommended next action.

If a human asks you to persist a standing rule after an incident, ask for confirmation and then store *only the rule/decision*, not raw logs.
"""


def build_outputs() -> dict[Path, str]:
    global_card = _read(GLOBAL_CARD)
    readonly_card = _read(READONLY_CARD)
    return {
        DOCS_DIR / "agent-memory-skill-cards.md": _render_cards_doc(global_card, readonly_card),
        SNIPPETS_DIR / "openclaw-agentturn-message.global-default.md": _render_global_snippet(global_card),
        SNIPPETS_DIR / "openclaw-agentturn-message.watchdog-readonly.md": _render_readonly_snippet(readonly_card),
    }


def write_outputs() -> list[Path]:
    changed: list[Path] = []
    for path, content in build_outputs().items():
        path.parent.mkdir(parents=True, exist_ok=True)
        existing = path.read_text(encoding="utf-8") if path.exists() else None
        normalized = content.rstrip() + "\n"
        if existing != normalized:
            path.write_text(normalized, encoding="utf-8")
            changed.append(path)
    return changed


def check_outputs() -> list[Path]:
    stale: list[Path] = []
    for path, content in build_outputs().items():
        normalized = content.rstrip() + "\n"
        existing = path.read_text(encoding="utf-8") if path.exists() else None
        if existing != normalized:
            stale.append(path)
    return stale


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description="Generate agent-memory skill docs/snippets from canonical skill cards.")
    parser.add_argument("--check", action="store_true", help="Fail if generated files are out of date.")
    args = parser.parse_args(argv)

    if args.check:
        stale = check_outputs()
        if stale:
            for path in stale:
                print(f"STALE {path.relative_to(REPO_ROOT)}")
            return 1
        print("OK agent-memory skill assets are up to date")
        return 0

    changed = write_outputs()
    if changed:
        for path in changed:
            print(f"WROTE {path.relative_to(REPO_ROOT)}")
    else:
        print("UNCHANGED agent-memory skill assets")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
