"""ANSYS Mechanical 2024 R2 declarative geometry-inspection adapter."""

from __future__ import annotations

import json
import os
import sys
from importlib.metadata import version
from pathlib import Path
from typing import Any

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from ansys_geometry import (  # noqa: E402
    ANSYS_REVISION,
    EXECUTION_GATE,
    artifact_manifest,
    atomic_json,
    export_geometry_image,
    file_sha256,
    geometry_inventory,
    import_geometry,
    input_file,
    probe,
    terminal,
    validate_artifact,
)

ADAPTER_VERSION = "0.3.0"
_ARTIFACTS = {
    "geometry-manifest.json": ("geometry_manifest", "application/json"),
    "geometry-preview.png": ("geometry_preview", "image/png"),
    "provenance.json": ("provenance", "application/json"),
}


def _validate_semantics(request: dict[str, Any]) -> None:
    inspect = request["operation"]["inspect"]
    input_keys = {item["key"] for item in request["inputs"]}
    if inspect["geometry"]["input"] not in input_keys:
        raise ValueError("GEOMETRY_INPUT_NOT_BOUND")
    if request["outputs"]:
        raise ValueError("INSPECT_OUTPUTS_MUST_BE_EMPTY")


def _load_request(job_dir: Path) -> dict[str, Any]:
    record = json.loads(
        (job_dir / "request" / "request.json").read_text(encoding="utf-8")
    )
    request = record.get("request")
    if not isinstance(request, dict):
        raise TypeError("JOB_REQUEST_MISSING")
    _validate_semantics(request)
    return record


def run(job_dir: Path) -> list[dict[str, Any]]:
    job_dir = job_dir.resolve(strict=True)
    record = _load_request(job_dir)
    request = record["request"]
    inspect = request["operation"]["inspect"]
    geometry = input_file(job_dir, inspect["geometry"]["input"])
    output = job_dir / "output"
    output.mkdir(exist_ok=True)

    from ansys.mechanical.core import App

    software_version: int | None = None
    manifest_path = output / "geometry-manifest.json"
    preview_path = output / "geometry-preview.png"
    with App(version=ANSYS_REVISION, private_appdata=True) as app:
        software_version = app.version
        api: dict[str, Any] = {}
        app.update_globals(api)
        import_geometry(app, api, geometry)
        inventory, _ = geometry_inventory(app)
        inventory.update(
            {
                "title": inspect["title"],
                "software": "ANSYS Mechanical",
                "software_version": software_version,
            }
        )
        atomic_json(manifest_path, inventory)
        export_geometry_image(app, api, preview_path)

    provenance_path = output / "provenance.json"
    atomic_json(
        provenance_path,
        {
            "adapter_version": ADAPTER_VERSION,
            "pymechanical_version": version("ansys-mechanical-core"),
            "ansys_revision": ANSYS_REVISION,
            "request_digest": record["request_digest"],
            "input": {
                "key": inspect["geometry"]["input"],
                "filename": geometry.name,
                "sha256": file_sha256(geometry),
            },
        },
    )
    paths = [manifest_path, preview_path, provenance_path]
    for path in paths:
        validate_artifact(path)
    return [artifact_manifest(path, _ARTIFACTS) for path in paths]


def main() -> int:
    if sys.argv[1:] == ["--probe"]:
        return probe(ADAPTER_VERSION)
    if len(sys.argv) != 2:
        print("[ERR] Usage: worker.py <job-directory>", file=sys.stderr)
        return 2
    job_dir = Path(sys.argv[1])
    record: dict[str, Any] = {}
    try:
        record = _load_request(job_dir)
        if os.environ.get(EXECUTION_GATE) != "1":
            raise RuntimeError("ANSYS_242_REAL_LICENSE_ACCEPTANCE_REQUIRED")
        artifacts = run(job_dir)
        atomic_json(job_dir / "artifacts.json", artifacts)
        atomic_json(job_dir / "terminal.json", terminal(record, "succeeded", artifacts, {}))
        print("[OK] ANSYS Mechanical geometry inspection completed.")
        return 0
    except Exception as exc:  # noqa: BLE001 - terminal.json must capture vendor failures
        atomic_json(
            job_dir / "terminal.json",
            terminal(
                record,
                "failed",
                [],
                {"code": type(exc).__name__, "detail": str(exc)[:500]},
            ),
        )
        print(f"[ERR] {type(exc).__name__}: {exc}", file=sys.stderr)
        return 1


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