#!/usr/bin/env python3
"""Verify CARBON IP and executable logic live in the plugin runtime, not skills."""

from __future__ import annotations

import json
import subprocess
from pathlib import Path


PLUGIN = Path(__file__).resolve().parents[1]
SKILLS = PLUGIN / "skills"
RUNTIME = PLUGIN / "runtime" / "carbon"
LAUNCHER = PLUGIN / "bin" / "carbon-runtime"


def run(*args: str) -> str:
    result = subprocess.run(
        [str(LAUNCHER), *args], text=True, capture_output=True, check=False
    )
    if result.returncode:
        raise AssertionError(
            f"carbon-runtime {' '.join(args)} failed:\n{result.stderr or result.stdout}"
        )
    return result.stdout


if not LAUNCHER.is_file() or not LAUNCHER.stat().st_mode & 0o111:
    raise AssertionError("plugin-level carbon-runtime launcher is missing or not executable")

required_runtime = [
    RUNTIME / "scripts" / "carbon_advisor.py",
    RUNTIME / "scripts" / "carbon_framework.py",
    RUNTIME / "scripts" / "carbon_run.py",
    RUNTIME / "scripts" / "carbon_plan_view.py",
    RUNTIME / "scripts" / "carbon_browser.py",
    RUNTIME / "scripts" / "carbon_evidence.py",
    RUNTIME / "scripts" / "carbon_persona_journeys.py",
    RUNTIME / "scripts" / "carbon_bake.py",
    RUNTIME / "scripts" / "carbon_quality_confidence.py",
    RUNTIME / "scripts" / "carbon_intelligence.py",
    RUNTIME / "scripts" / "carbon_context.py",
    RUNTIME / "scripts" / "carbon_command_report.py",
    RUNTIME / "scripts" / "carbon_chatbot.py",
    RUNTIME / "scripts" / "carbon_ai_upgrade.py",
    RUNTIME / "scripts" / "carbon_failure.py",
    RUNTIME / "scripts" / "carbon_promotions.py",
    RUNTIME / "scripts" / "select_items.py",
    RUNTIME / "scripts" / "select_flows.py",
    RUNTIME / "references" / "items",
    RUNTIME / "references" / "flows",
    RUNTIME / "references" / "execution" / "plan-contract.md",
    RUNTIME / "references" / "browser" / "carbon-browser-v1.json",
    RUNTIME / "references" / "chatbot-testing.md",
    RUNTIME / "references" / "ai-upgrade-visual-checks.md",
    RUNTIME / "references" / "testing-doctrine.md",
    RUNTIME / "references" / "testing-doctrine.json",
    RUNTIME / "references" / "intelligence-layer.md",
    RUNTIME / "benchmarks" / "seeded-defects" / "manifest.json",
    RUNTIME / "templates" / "carbon_ai_visual_check.py",
]
missing = [str(path.relative_to(PLUGIN)) for path in required_runtime if not path.exists()]
if missing:
    raise AssertionError(f"plugin runtime is incomplete: {missing}")

skill_ip_paths = [
    path.relative_to(PLUGIN).as_posix()
    for path in SKILLS.rglob("*")
    if path.is_file() and ({"scripts", "references"} & set(path.relative_to(SKILLS).parts))
]
if skill_ip_paths:
    raise AssertionError(f"framework logic or reference IP remains in skills: {skill_ip_paths}")

skill_markdown = list(SKILLS.rglob("*.md"))
skill_markdown_bytes = sum(path.stat().st_size for path in skill_markdown)
runtime_bytes = sum(path.stat().st_size for path in RUNTIME.rglob("*") if path.is_file())
skill_markdown_budget = len(list(SKILLS.glob("*/SKILL.md"))) * 4_500
if skill_markdown_bytes > skill_markdown_budget:
    raise AssertionError(f"skill Markdown is no longer thin: {skill_markdown_bytes} bytes")
if runtime_bytes < skill_markdown_bytes * 8:
    raise AssertionError(
        f"plugin runtime should dominate skill Markdown by at least 8x: runtime={runtime_bytes}, skills={skill_markdown_bytes}"
    )

main_skill = (SKILLS / "carbon" / "SKILL.md").read_text(encoding="utf-8")
if len(main_skill.encode("utf-8")) > 12_000:
    raise AssertionError("main CARBON skill has accumulated framework implementation detail")
for phrase in ("host-facing router", "../../runtime/carbon/", "../../bin/carbon-runtime", "anonymous opinionated testing doctrine"):
    if phrase not in main_skill:
        raise AssertionError(f"main CARBON skill is missing runtime routing phrase: {phrase}")

server_source = (PLUGIN / "server" / "index.js").read_text(encoding="utf-8")
if '"runtime", "carbon"' not in server_source:
    raise AssertionError("MCP server does not resolve the plugin-level CARBON runtime")
if '"skills", "carbon", "scripts"' in server_source:
    raise AssertionError("MCP server still executes framework logic from a skill directory")

help_text = run("help")
for command in ("advise", "framework", "run", "plan-view", "browser", "evidence", "learn", "record", "intent", "bake", "context", "command-report", "chatbot", "ai-upgrade", "failure", "intelligence", "select-items", "select-flows"):
    if command not in help_text:
        raise AssertionError(f"runtime launcher does not expose {command}")

items = json.loads(run("select-items", "--json", "email", "checkout"))
flows = json.loads(run("select-flows", "--json", "checkout"))
if not items.get("references") or not flows.get("references"):
    raise AssertionError("runtime selectors did not resolve plugin-level test packs")
if not any("flows/commerce/checkout.md" in value for value in flows["references"]):
    raise AssertionError("runtime flow selector did not resolve checkout")

multi_flows = json.loads(
    run("select-flows", "--json", "create edit delete task settings")
)
multi_references = set(multi_flows.get("references", []))
for expected in (
    "flows/productivity/create-edit-delete-record.md",
    "flows/engagement/settings-preferences.md",
):
    if expected not in multi_references:
        raise AssertionError(
            f"runtime flow selector dropped a multi-intent flow: {expected}"
        )

print(json.dumps({
    "status": "PASS",
    "skillMarkdownBytes": skill_markdown_bytes,
    "runtimeBytes": runtime_bytes,
    "runtimeToSkillRatio": round(runtime_bytes / max(1, skill_markdown_bytes), 1),
    "skillReferenceOrScriptFiles": len(skill_ip_paths),
    "launcher": str(LAUNCHER),
}, indent=2))
