"""
@docs ARCHITECTURE:Registry:Skills

### AI Assist Note
**Skill: vulnerability-scanner**
Advanced agentic logic and tool orchestration for the Tadpole OS swarm.

### 🔍 Debugging & Observability
- **Failure Path**: Script error, API failure, or logic drift in the 3-layer architecture.
- **Telemetry Link**: Search `[dependency_analyzer]` in system logs.
"""

#!/usr/bin/env python3
"""
Skill: vulnerability-scanner
Script: dependency_analyzer.py
Purpose: Formal dependency audit for Tadpole OS supply chain security.
Usage: python dependency_analyzer.py <project_path>
"""
import subprocess
import json
import os
import sys
import shutil
import platform
from pathlib import Path
from datetime import datetime
from typing import List, Dict, Any, Optional

# Resolve npm executable — on Windows it is 'npm.cmd'; shutil.which handles this.
_NPM_CMD: str = shutil.which("npm") or ("npm.cmd" if platform.system() == "Windows" else "npm")

def analyze_dependencies(project_path: str):
    report = {
        "timestamp": datetime.now().isoformat(),
        "project": project_path,
        "findings": [],
        "summary": {"critical": 0, "high": 0, "moderate": 0, "low": 0}
    }

    # 1. Node.js Audit
    pkg_json = Path(project_path) / "package.json"
    if pkg_json.exists():
        try:
            result = subprocess.run(
                [_NPM_CMD, "audit", "--json"],
                cwd=project_path,
                capture_output=True,
                text=True,
                timeout=60
            )
            audit_data = json.loads(result.stdout)
            vulns = audit_data.get("metadata", {}).get("vulnerabilities", {})
            for sev in ["critical", "high", "moderate", "low"]:
                count = vulns.get(sev, 0)
                report["summary"][sev] += count
                if count > 0:
                    report["findings"].append({
                        "type": "npm-vulnerability",
                        "severity": sev,
                        "message": f"Found {count} {sev} vulnerabilities in Node.js dependencies."
                    })
        except Exception as e:
            report["findings"].append({"type": "error", "severity": "medium", "message": f"npm audit failed: {str(e)}"})

    # 2. Rust/Cargo Audit (if available)
    cargo_toml = Path(project_path) / "server-rs" / "Cargo.toml"
    if cargo_toml.exists():
        # Check for cargo audit tool
        try:
            res = subprocess.run(["cargo", "audit", "--version"], capture_output=True)
            if res.returncode == 0:
                result = subprocess.run(
                    ["cargo", "audit", "--json"],
                    cwd=str(Path(project_path) / "server-rs"),
                    capture_output=True,
                    text=True,
                    timeout=120
                )
                # Parse cargo audit output...
                # (Simulated for now, as cargo audit is often not in standard CI runners)
            else:
                report["findings"].append({
                    "type": "tool-missing",
                    "severity": "low",
                    "message": "cargo-audit not installed. Skipping deep Rust dependency scan."
                })
        except Exception:
             pass

    # 3. Lock File Integrity
    for manager, files in [("npm", ["package-lock.json"]), ("cargo", ["Cargo.lock"])]:
        has_pkg = (Path(project_path) / "package.json").exists() if manager == "npm" else (Path(project_path) / "server-rs" / "Cargo.toml").exists()
        if has_pkg:
            lock_found = any((Path(project_path) / f if manager == "npm" else Path(project_path) / "server-rs" / f).exists() for f in files)
            if not lock_found:
                report["findings"].append({
                    "type": "missing-lockfile",
                    "severity": "high",
                    "message": f"Missing lockfile for {manager}. Supply chain integrity at risk."
                })
                report["summary"]["high"] += 1

    return report

if __name__ == "__main__":
    path = sys.argv[1] if len(sys.argv) > 1 else "."
    print(json.dumps(analyze_dependencies(path), indent=2))

# Metadata: [dependency_analyzer]
