import json
from types import MappingProxyType


def test_weights_cli_template_manifest_emits_json(capsys):
    from pyimgano.weights_cli import main

    rc = main(["template", "manifest"])
    assert rc == 0

    out = json.loads(capsys.readouterr().out)
    assert out["schema_version"] == 1
    assert isinstance(out["entries"], list)
    assert out["entries"][0]["license"] == "internal-or-upstream-license"


def test_weights_cli_template_model_card_emits_json(capsys):
    from pyimgano.weights_cli import main

    rc = main(["template", "model-card"])
    assert rc == 0

    out = json.loads(capsys.readouterr().out)
    assert out["schema_version"] == 1
    assert out["model_name"] == "example_model_name"
    assert out["deployment"]["runtime"] == "torch"


def test_weights_cli_validate_model_card_json_success(tmp_path, capsys):
    from pyimgano.weights_cli import main

    payload = {
        "schema_version": 1,
        "model_name": "demo_model",
        "summary": {
            "purpose": "demo",
            "intended_inputs": "RGB",
            "output_contract": "image-level",
        },
        "weights": {
            "path": "checkpoints/demo.pt",
            "source": "unit-test",
            "license": "internal",
        },
        "deployment": {"runtime": "torch"},
    }
    path = tmp_path / "model_card.json"
    path.write_text(json.dumps(payload), encoding="utf-8")

    rc = main(["validate-model-card", str(path), "--json"])
    assert rc == 0

    out = json.loads(capsys.readouterr().out)
    assert out["ok"] is True
    assert out["normalized"]["model_name"] == "demo_model"


def test_weights_cli_validate_model_card_can_check_files_and_hashes(tmp_path, capsys):
    from pyimgano.weights_cli import main

    ckpt = tmp_path / "checkpoints" / "demo.pt"
    ckpt.parent.mkdir(parents=True, exist_ok=True)
    data = b"demo-weights"
    ckpt.write_bytes(data)

    import hashlib

    sha = hashlib.sha256(data).hexdigest()

    payload = {
        "schema_version": 1,
        "model_name": "demo_model",
        "summary": {
            "purpose": "demo",
            "intended_inputs": "RGB",
            "output_contract": "image-level",
        },
        "weights": {
            "path": "checkpoints/demo.pt",
            "sha256": sha,
            "source": "unit-test",
            "license": "internal",
        },
        "deployment": {"runtime": "torch"},
    }
    path = tmp_path / "model_card.json"
    path.write_text(json.dumps(payload), encoding="utf-8")

    rc = main(
        [
            "validate-model-card",
            str(path),
            "--check-files",
            "--check-hashes",
            "--json",
        ]
    )
    assert rc == 0

    out = json.loads(capsys.readouterr().out)
    assert out["ok"] is True
    assert out["assets"]["weights"]["exists"] is True
    assert out["assets"]["weights"]["sha256_match"] is True


def test_weights_cli_validate_model_card_can_cross_check_manifest(tmp_path, capsys):
    from pyimgano.weights_cli import main

    ckpt = tmp_path / "checkpoints" / "demo.pt"
    ckpt.parent.mkdir(parents=True, exist_ok=True)
    data = b"demo-weights"
    ckpt.write_bytes(data)

    import hashlib

    sha = hashlib.sha256(data).hexdigest()

    manifest = {
        "schema_version": 1,
        "entries": [
            {
                "name": "demo_model_entry",
                "path": "checkpoints/demo.pt",
                "sha256": sha,
                "source": "unit-test",
                "license": "internal",
                "runtime": "torch",
            }
        ],
    }
    manifest_path = tmp_path / "weights_manifest.json"
    manifest_path.write_text(json.dumps(manifest), encoding="utf-8")

    payload = {
        "schema_version": 1,
        "model_name": "demo_model",
        "summary": {
            "purpose": "demo",
            "intended_inputs": "RGB",
            "output_contract": "image-level",
        },
        "weights": {
            "path": "checkpoints/demo.pt",
            "sha256": sha,
            "source": "unit-test",
            "license": "internal",
            "manifest_entry": "demo_model_entry",
        },
        "deployment": {"runtime": "torch"},
    }
    path = tmp_path / "model_card.json"
    path.write_text(json.dumps(payload), encoding="utf-8")

    rc = main(
        [
            "validate-model-card",
            str(path),
            "--manifest",
            str(manifest_path),
            "--check-files",
            "--check-hashes",
            "--json",
        ]
    )
    assert rc == 0

    out = json.loads(capsys.readouterr().out)
    assert out["ok"] is True
    assert out["assets"]["manifest"]["matched_entry"] == "demo_model_entry"
    trust = out["trust_summary"]
    assert trust["status"] == "trust-signaled"
    assert trust["trust_signals"]["has_weights_sha256"] is True
    assert trust["trust_signals"]["has_manifest_link"] is True
    assert trust["trust_signals"]["has_cross_checked_manifest"] is True
    assert trust["audit_refs"]["model_card_json"] == str(path)
    assert trust["audit_refs"]["weights_manifest_json"] == str(manifest_path)


def test_weights_cli_validate_manifest_json_includes_trust_summary(tmp_path, capsys):
    from pyimgano.weights_cli import main

    ckpt = tmp_path / "checkpoints" / "demo.pt"
    ckpt.parent.mkdir(parents=True, exist_ok=True)
    data = b"demo-weights"
    ckpt.write_bytes(data)

    import hashlib

    sha = hashlib.sha256(data).hexdigest()

    manifest = {
        "schema_version": 1,
        "entries": [
            {
                "name": "demo_model_entry",
                "path": "checkpoints/demo.pt",
                "sha256": sha,
                "source": "unit-test",
                "license": "internal",
                "runtime": "torch",
            }
        ],
    }
    manifest_path = tmp_path / "weights_manifest.json"
    manifest_path.write_text(json.dumps(manifest), encoding="utf-8")

    rc = main(
        [
            "validate",
            str(manifest_path),
            "--check-files",
            "--check-hashes",
            "--json",
        ]
    )
    assert rc == 0

    out = json.loads(capsys.readouterr().out)
    trust = out["trust_summary"]
    assert trust["status"] == "trust-signaled"
    assert trust["trust_signals"]["all_entries_have_sha256"] is True
    assert trust["trust_signals"]["all_entries_have_source"] is True
    assert trust["trust_signals"]["all_entries_have_license"] is True
    assert trust["trust_signals"]["all_entries_have_runtime"] is True
    assert trust["audit_refs"]["weights_manifest_json"] == str(manifest_path)


def test_weights_cli_validate_manifest_plain_output_prints_check_strength(
    tmp_path, capsys
):
    from pyimgano.weights_cli import main

    ckpt = tmp_path / "checkpoints" / "demo.pt"
    ckpt.parent.mkdir(parents=True, exist_ok=True)
    ckpt.write_bytes(b"demo-weights")

    manifest = {
        "schema_version": 1,
        "entries": [
            {
                "name": "demo_model_entry",
                "path": "checkpoints/demo.pt",
                "sha256": "a" * 64,
                "source": "unit-test",
                "license": "internal",
                "runtime": "torch",
            }
        ],
    }
    manifest_path = tmp_path / "weights_manifest.json"
    manifest_path.write_text(json.dumps(manifest), encoding="utf-8")

    rc = main(
        [
            "validate",
            str(manifest_path),
            "--check-files",
        ]
    )
    assert rc == 0

    out = capsys.readouterr().out.lower()
    assert "trust_signal.file_refs_checked=true" in out
    assert "trust_signal.hashes_checked=false" in out


def test_weights_cli_validate_model_card_json_includes_check_strength(
    tmp_path, capsys
):
    from pyimgano.weights_cli import main

    ckpt = tmp_path / "checkpoints" / "demo.pt"
    ckpt.parent.mkdir(parents=True, exist_ok=True)
    data = b"demo-weights"
    ckpt.write_bytes(data)

    import hashlib

    sha = hashlib.sha256(data).hexdigest()

    payload = {
        "schema_version": 1,
        "model_name": "demo_model",
        "summary": {
            "purpose": "demo",
            "intended_inputs": "RGB",
            "output_contract": "image-level",
        },
        "weights": {
            "path": "checkpoints/demo.pt",
            "sha256": sha,
            "source": "unit-test",
            "license": "internal",
        },
        "deployment": {"runtime": "torch"},
    }
    path = tmp_path / "model_card.json"
    path.write_text(json.dumps(payload), encoding="utf-8")

    rc = main(
        [
            "validate-model-card",
            str(path),
            "--check-files",
            "--check-hashes",
            "--json",
        ]
    )
    assert rc == 0

    out = json.loads(capsys.readouterr().out)
    trust = out["trust_summary"]
    assert trust["trust_signals"]["file_refs_checked"] is True
    assert trust["trust_signals"]["hashes_checked"] is True


def test_build_model_card_trust_summary_accepts_mapping_inputs() -> None:
    from pyimgano.weights_cli import _build_model_card_trust_summary

    class _Report:
        ok = True
        normalized = MappingProxyType(
            {
                "weights": MappingProxyType(
                    {
                        "sha256": "a" * 64,
                        "source": "unit-test",
                        "license": "internal",
                        "manifest_entry": "demo_model",
                    }
                ),
                "deployment": MappingProxyType({"runtime": "torch"}),
            }
        )
        assets = MappingProxyType(
            {
                "manifest": MappingProxyType(
                    {
                        "matched_entry": "demo_model",
                        "ok": True,
                    }
                )
            }
        )

    trust = _build_model_card_trust_summary(
        _Report(),
        model_card_path="/tmp/model_card.json",
        manifest_path="/tmp/weights_manifest.json",
        check_files=True,
        check_hashes=False,
    )

    assert trust["status"] == "trust-signaled"
    assert trust["trust_signals"]["has_weights_sha256"] is True
    assert trust["trust_signals"]["has_manifest_link"] is True
    assert trust["trust_signals"]["has_cross_checked_manifest"] is True


def test_weights_cli_audit_bundle_json_success(tmp_path, capsys):
    from pyimgano.weights_cli import main

    ckpt = tmp_path / "deploy_bundle" / "model.pt"
    ckpt.parent.mkdir(parents=True, exist_ok=True)
    data = b"bundle-weights"
    ckpt.write_bytes(data)

    import hashlib

    sha = hashlib.sha256(data).hexdigest()

    model_card = {
        "schema_version": 1,
        "model_name": "bundle_model",
        "summary": {
            "purpose": "bundle validation",
            "intended_inputs": "RGB",
            "output_contract": "image-level",
        },
        "weights": {
            "path": "model.pt",
            "manifest_entry": "bundle_model",
            "sha256": sha,
            "source": "unit-test",
            "license": "internal",
        },
        "deployment": {"runtime": "torch"},
    }
    manifest = {
        "schema_version": 1,
        "entries": [
            {
                "name": "bundle_model",
                "path": "model.pt",
                "sha256": sha,
                "source": "unit-test",
                "license": "internal",
                "runtime": "torch",
            }
        ],
    }
    (tmp_path / "deploy_bundle" / "model_card.json").write_text(
        json.dumps(model_card),
        encoding="utf-8",
    )
    (tmp_path / "deploy_bundle" / "weights_manifest.json").write_text(
        json.dumps(manifest),
        encoding="utf-8",
    )

    rc = main(
        [
            "audit-bundle",
            str(tmp_path / "deploy_bundle"),
            "--check-hashes",
            "--json",
        ]
    )

    assert rc == 0
    out = json.loads(capsys.readouterr().out)
    assert out["status"] == "ready"
    assert out["ready"] is True
    assert out["missing_required"] == []
    assert out["model_card"]["valid"] is True
    assert out["weights_manifest"]["valid"] is True
    assert out["cross_checked"] is True
    trust = out["trust_summary"]
    assert trust["status"] == "trust-signaled"
    assert trust["trust_signals"]["has_model_card"] is True
    assert trust["trust_signals"]["has_weights_manifest"] is True
    assert trust["trust_signals"]["has_cross_checked_manifest"] is True


def test_weights_cli_audit_bundle_requires_model_card_and_manifest(tmp_path, capsys):
    from pyimgano.weights_cli import main

    bundle_dir = tmp_path / "deploy_bundle"
    bundle_dir.mkdir(parents=True, exist_ok=True)

    rc = main(["audit-bundle", str(bundle_dir), "--json"])

    assert rc == 1
    out = json.loads(capsys.readouterr().out)
    assert out["status"] == "partial"
    assert out["ready"] is False
    assert "model_card.json" in out["missing_required"]
    assert "weights_manifest.json" in out["missing_required"]
    assert out["trust_summary"]["status"] == "partial"
