#!/usr/bin/env python3
"""Probe PL optimizer compatibility without assuming a specific Vivado version."""

from __future__ import annotations

import argparse
import json
import shutil
import subprocess
import sys
from pathlib import Path
from typing import Any


def load_json(path: Path) -> dict[str, Any]:
    return json.loads(path.read_text(encoding="utf-8"))


def find_vivado(explicit: str | None) -> str | None:
    if explicit:
        return explicit
    return shutil.which("vivado") or shutil.which("vivado.bat")


def run_vivado_version(vivado: str, timeout_s: int) -> tuple[bool, str]:
    try:
        proc = subprocess.run(
            [vivado, "-version"],
            text=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            timeout=timeout_s,
        )
    except Exception as exc:
        return False, str(exc)
    return proc.returncode == 0, proc.stdout.strip()


def rapidwright_import_status() -> tuple[bool, str]:
    try:
        import rapidwright  # type: ignore
    except Exception as exc:
        return False, str(exc)
    return True, getattr(rapidwright, "__version__", "imported")


def dcp_status(path: str | None) -> dict[str, Any]:
    if not path:
        return {"provided": False}
    dcp = Path(path)
    return {
        "provided": True,
        "path": str(dcp),
        "exists": dcp.exists(),
        "size": dcp.stat().st_size if dcp.exists() else None,
    }


def classify(profile: dict[str, Any], vivado_ok: bool, rapidwright_ok: bool, dcp: dict[str, Any]) -> dict[str, Any]:
    mode_order = profile.get("mode_order", [])
    available_modes: list[str] = []
    blocked: list[str] = []

    if vivado_ok:
        available_modes.append("vivado_only")
    else:
        blocked.append("vivado_only: Vivado not found or not runnable")

    if rapidwright_ok and dcp.get("exists"):
        available_modes.append("rapidwright_read_only_after_probe")
    else:
        blocked.append("rapidwright_read_only_after_probe: RapidWright import and existing DCP required")

    blocked.append("rapidwright_writeback_after_roundtrip: requires explicit DCP roundtrip validation")

    return {
        "recommended_first_mode": available_modes[0] if available_modes else "collect_environment_only",
        "profile_mode_order": mode_order,
        "available_modes": available_modes,
        "blocked_modes": blocked,
    }


def main(argv: list[str]) -> int:
    parser = argparse.ArgumentParser(description="Probe PL optimizer compatibility")
    parser.add_argument("--profile", required=True, help="version profile JSON")
    parser.add_argument("--vivado", default=None, help="Vivado executable path")
    parser.add_argument("--dcp", default=None, help="optional isolated DCP path")
    parser.add_argument("--timeout-s", type=int, default=60)
    args = parser.parse_args(argv)

    profile_path = Path(args.profile).resolve()
    profile = load_json(profile_path)

    vivado = find_vivado(args.vivado)
    vivado_ok = False
    vivado_version = "not found"
    if vivado:
        vivado_ok, vivado_version = run_vivado_version(vivado, args.timeout_s)

    rapidwright_ok, rapidwright_version = rapidwright_import_status()
    dcp = dcp_status(args.dcp)
    decision = classify(profile, vivado_ok, rapidwright_ok, dcp)

    result = {
        "profile": str(profile_path),
        "target_vivado_version": profile.get("vivado_version"),
        "vivado": {
            "path": vivado,
            "ok": vivado_ok,
            "version_output": vivado_version,
        },
        "rapidwright": {
            "ok": rapidwright_ok,
            "version": rapidwright_version,
            "policy": profile.get("rapidwright_policy", {}),
        },
        "dcp": dcp,
        "decision": decision,
        "safe_automatic_actions": profile.get("safe_automatic_actions", []),
        "human_authorization_required": profile.get("human_authorization_required", []),
    }
    print(json.dumps(result, indent=2, ensure_ascii=False))
    return 0 if vivado_ok else 2


if __name__ == "__main__":
    raise SystemExit(main(sys.argv[1:]))
