#!/usr/bin/env python3
"""Validate one installed app against Platform App Standard v1."""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(BASE_DIR))
loaded_platform = sys.modules.get("platform")
if loaded_platform is not None and not hasattr(loaded_platform, "__path__"):
    del sys.modules["platform"]

from bridge_platform.apps.registry import AppContractError, load_manifest
from bridge_platform.agents.tool_catalog import manifest_tools


REQUIRED_FILES = ("__init__.py", "README.md", "APP_MANUAL.md")
REQUIRED_MANUAL_SECTIONS = (
    "## Contract",
    "## Exported capabilities",
    "## Error contract",
    "## Security and tenant isolation",
    "## Observability",
    "## Testing and validation",
    "## Versioning and compatibility",
)


def validate_layout(manifest) -> list[str]:
    errors: list[str] = []
    app_root = BASE_DIR / "apps" / manifest.app_id
    for relative in REQUIRED_FILES:
        if not (app_root / relative).is_file():
            errors.append(f"required app file is missing: {relative}")
    manual_path = app_root / "APP_MANUAL.md"
    if manual_path.is_file():
        manual = manual_path.read_text(encoding="utf-8")
        for heading in REQUIRED_MANUAL_SECTIONS:
            if heading not in manual:
                errors.append(f"app manual is missing section: {heading}")
    package = manifest.wordpress_package
    if package:
        source = app_root / package.source_directory
        package_manifest_path = source / "wordpress-app-pack.json"
        entrypoint = source / package.entrypoint
        if not package_manifest_path.is_file() or not entrypoint.is_file():
            errors.append("WordPress package source manifest or entrypoint is missing")
            return errors
        source_manifest = json.loads(package_manifest_path.read_text(encoding="utf-8"))
        expected = {
            "package_id": package.package_id,
            "app_id": manifest.app_id,
            "version": package.version,
            "entrypoint": package.entrypoint,
            "plugin_file": package.plugin_file,
            "capabilities": list(package.capabilities),
            "minimum_bridge_version": package.minimum_bridge_version,
            "minimum_wordpress_version": package.minimum_wordpress_version,
            "minimum_php_version": package.minimum_php_version,
            "contains_secrets": False,
        }
        for key, value in expected.items():
            if source_manifest.get(key) != value:
                errors.append(f"WordPress package source mismatch: {key}")
    return errors


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("app_id")
    args = parser.parse_args()
    try:
        manifest = load_manifest(args.app_id)
        if manifest is None:
            raise AppContractError("APP_MANIFEST is missing (legacy app)")
        layout_errors = validate_layout(manifest)
        if layout_errors:
            raise AppContractError("; ".join(layout_errors))
    except (AppContractError, ImportError) as exc:
        print(json.dumps({"status": "invalid", "app_id": args.app_id, "errors": [str(exc)]}, indent=2))
        return 1
    print(json.dumps({
        "status": "valid",
        "app_id": manifest.app_id,
        "contract_version": manifest.contract_version,
        "actions": sorted(manifest.actions),
        "capabilities": sorted(action.capability for action in manifest.actions.values()),
        "agent_tools": [
            {
                "capability": tool["capability"],
                "risk": tool["risk"],
                "confirmation": tool["confirmation"],
            }
            for tool in manifest_tools(manifest)
        ],
        "requirements": {
            "semantic_version": True,
            "versioned_actions": True,
            "stable_error_codes": True,
            "manual": True,
            "tenant_isolation": True,
            "structured_observability": True,
        },
        "wordpress_package": None if manifest.wordpress_package is None else {
            "package_id": manifest.wordpress_package.package_id,
            "version": manifest.wordpress_package.version,
            "source_validated": True,
            "release_metadata_external": not bool(manifest.wordpress_package.signature),
        },
    }, indent=2))
    return 0


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