#!/usr/bin/env python3
from __future__ import annotations

import argparse
import json
import subprocess
from pathlib import Path

LIVE_TEMPLATES_DIR = Path.home() / ".nanobot" / "cards" / "templates"
EXAMPLE_TEMPLATES_DIR = (
    Path(__file__).resolve().parent.parent / "examples" / "cards" / "templates"
)


LEGACY_MARKERS = (
    "__nanobot",
    "document.currentScript",
    "mountLegacyTemplate",
    "legacy-template-module",
)


def iter_template_dirs(root: Path) -> dict[str, Path]:
    templates: dict[str, Path] = {}
    if not root.exists():
        return templates
    for child in sorted(root.iterdir()):
        if not child.is_dir():
            continue
        if not (child / "manifest.json").exists():
            continue
        templates[child.name] = child
    return templates


def validate_template_dir(template_dir: Path, failures: list[str]) -> None:
    manifest_path = template_dir / "manifest.json"
    template_path = template_dir / "template.html"
    runtime_path = template_dir / "card.js"

    for required in (manifest_path, template_path, runtime_path):
        if not required.exists():
            failures.append(f"{template_dir}: missing {required.name}")
            return

    try:
        manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
    except Exception as exc:
        failures.append(f"{manifest_path}: invalid JSON ({exc})")
        return
    if not isinstance(manifest, dict):
        failures.append(f"{manifest_path}: manifest must be an object")

    template_html = template_path.read_text(encoding="utf-8")
    if "<script" in template_html.lower():
        failures.append(f"{template_path}: inline script tags are not allowed")

    runtime_js = runtime_path.read_text(encoding="utf-8")
    if "export function mount" not in runtime_js:
        failures.append(f"{runtime_path}: missing `export function mount`")
    for marker in LEGACY_MARKERS:
        if marker in runtime_js:
            failures.append(f"{runtime_path}: legacy marker `{marker}` still present")

    result = subprocess.run(
        ["node", "--check", str(runtime_path)],
        capture_output=True,
        text=True,
    )
    if result.returncode != 0:
        detail = (result.stderr or result.stdout).strip()
        failures.append(f"{runtime_path}: node --check failed: {detail}")


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--live-root", type=Path, default=LIVE_TEMPLATES_DIR)
    parser.add_argument("--example-root", type=Path, default=EXAMPLE_TEMPLATES_DIR)
    args = parser.parse_args()

    live_root = args.live_root.expanduser()
    example_root = args.example_root.expanduser()

    failures: list[str] = []
    for template_dir in iter_template_dirs(live_root).values():
        validate_template_dir(template_dir, failures)
    for template_dir in iter_template_dirs(example_root).values():
        validate_template_dir(template_dir, failures)

    sync_check = subprocess.run(
        [
            "python3",
            str(Path(__file__).resolve().parent / "sync_card_templates.py"),
            "--check",
            "--source",
            str(live_root),
            "--dest",
            str(example_root),
        ],
        capture_output=True,
        text=True,
    )
    if sync_check.returncode != 0:
        detail = (sync_check.stdout + sync_check.stderr).strip()
        if detail:
            print(detail)
        failures.append("template mirror drift detected")

    if failures:
        for failure in failures:
            print(failure)
        return 1

    print("card runtime ok")
    return 0


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