import argparse
import json
import os
import sys
import time
from pathlib import Path

PHASES = {"PLAN", "EXECUTE", "VERIFY", "COMMIT", "STATUS"}


def emit(phase, payload):
    if phase not in PHASES:
        raise ValueError("invalid phase")
    line = {"phase": phase, **payload}
    print(json.dumps(line, ensure_ascii=True))


def read_input(path):
    if path:
        data = Path(path).read_text(encoding="utf-8")
    else:
        data = sys.stdin.read()
    if not data.strip():
        raise ValueError("empty input")
    return json.loads(data)


def ensure_dir(path: Path):
    path.mkdir(parents=True, exist_ok=True)


def write_text(path: Path, content: str):
    path.write_text(content, encoding="utf-8")


def build_main_py(skill_id: str) -> str:
    return (
        "import json\n"
        "import sys\n"
        "from skills.registry import get_registry\n\n"
        "def read_payload(path=None):\n"
        "    if path:\n"
        "        data = open(path, 'r', encoding='utf-8').read()\n"
        "    else:\n"
        "        data = sys.stdin.read()\n"
        "    if not data.strip():\n"
        "        raise ValueError('empty input')\n"
        "    return json.loads(data)\n\n"
        "def emit(phase, payload):\n"
        "    print(json.dumps({**{'phase': phase}, **payload}, ensure_ascii=True))\n\n"
        "def main():\n"
        "    args = sys.argv[1:]\n"
        "    dry_run = '--dry-run' in args\n"
        "    input_path = None\n"
        "    if '--input' in args:\n"
        "        idx = args.index('--input')\n"
        "        if idx + 1 < len(args):\n"
        "            input_path = args[idx + 1]\n"
        "    payload = read_payload(input_path)\n"
        "    emit('PLAN', {'steps': ['execute skill', 'verify output', 'commit result']})\n"
        "    if dry_run:\n"
        "        emit('STATUS', {'status': 'FAILURE', 'reason': 'dry_run_no_change'})\n"
        "        return 2\n"
        f"    registry = get_registry()\n"
        f"    result = registry.execute_skill('{skill_id}', payload, context=None)\n"
        "    emit('EXECUTE', {'skill_id': '" + skill_id + "', 'success': result.success})\n"
        "    emit('VERIFY', {'success': bool(result.success)})\n"
        "    emit('COMMIT', {'record': {'skill_id': '" + skill_id + "', 'success': result.success}})\n"
        "    if result.success:\n"
        "        emit('STATUS', {'status': 'SUCCESS'})\n"
        "        return 0\n"
        "    emit('STATUS', {'status': 'FAILURE', 'reason': result.error or 'skill_failed'})\n"
        "    return 3\n\n"
        "if __name__ == '__main__':\n"
        "    raise SystemExit(main())\n"
    )


def main() -> int:
    parser = argparse.ArgumentParser(description="Create SBI wrapper artifacts")
    parser.add_argument("--input", help="JSON input file")
    parser.add_argument("--dry-run", action="store_true")
    args = parser.parse_args()

    data = read_input(args.input)
    name = data.get("name")
    version = data.get("version", "v1")
    skill_id = data.get("skill_id")
    output_root = Path(data.get("output_root", "skills"))

    if not name or not skill_id:
        emit("STATUS", {"status": "FAILURE", "reason": "missing_name_or_skill_id"})
        return 4

    target_dir = output_root / name / version
    commit_log = Path(data.get("commit_log", "runs/sbi_commits.jsonl"))

    plan_steps = [
        f"create {target_dir}",
        "write SKILL.md",
        "write main.py",
        "write manifest.json",
        f"append commit log {commit_log}",
    ]
    emit("PLAN", {"steps": plan_steps})

    if args.dry_run:
        emit("STATUS", {"status": "FAILURE", "reason": "dry_run_no_change"})
        return 2

    before_exists = target_dir.exists()
    ensure_dir(target_dir)

    skill_md = (
        "---\n"
        f"name: {name}\n"
        "description: SBI wrapper generated by sbi-artifactizer.\n"
        "---\n\n"
        "# SBI Wrapper\n\n"
        "Runs the source skill with deterministic phase output.\n"
    )

    manifest = {
        "name": name,
        "version": version,
        "skill_id": skill_id,
        "created_at": int(time.time()),
    }

    main_py = build_main_py(skill_id)

    write_text(target_dir / "SKILL.md", skill_md)
    write_text(target_dir / "main.py", main_py)
    write_text(target_dir / "manifest.json", json.dumps(manifest, indent=2))

    emit("EXECUTE", {"target": str(target_dir), "files": ["SKILL.md", "main.py", "manifest.json"]})

    verify_ok = all((target_dir / fname).exists() for fname in ["SKILL.md", "main.py", "manifest.json"])
    emit("VERIFY", {"success": verify_ok})

    if not verify_ok:
        emit("STATUS", {"status": "FAILURE", "reason": "verify_failed"})
        return 5

    commit_record = {
        "name": name,
        "version": version,
        "skill_id": skill_id,
        "target": str(target_dir),
        "timestamp": int(time.time()),
    }
    commit_log.parent.mkdir(parents=True, exist_ok=True)
    with commit_log.open("a", encoding="utf-8") as handle:
        handle.write(json.dumps(commit_record, ensure_ascii=True) + "\n")

    emit("COMMIT", {"record": commit_record, "log": str(commit_log)})

    if not before_exists and target_dir.exists():
        emit("STATUS", {"status": "SUCCESS"})
        return 0

    emit("STATUS", {"status": "FAILURE", "reason": "no_state_change"})
    return 6


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