"""Tests for meta-policies (REQ-303, v1.25).

Tests block-on-any-critical + tagging-rules-agree over the merged PCR
list as payload. Skips when kj is absent.
"""

import json
import os
import sys
from pathlib import Path

import pytest

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

import importlib.util
_ENGINE_PATH = Path(__file__).resolve().parent.parent / "adapters" / "kyverno-json" / "kyverno_json_engine.py"
_spec = importlib.util.spec_from_file_location("kyverno_json_engine", _ENGINE_PATH)
_mod = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_mod)
KyvernoJsonEngine = _mod.KyvernoJsonEngine

POLICY_DIR = Path(__file__).resolve().parent.parent / "adapters" / "kyverno-json" / "policies" / "meta"


def _kj_installed() -> bool:
    return _mod._which_kj() is not None


@pytest.fixture(autouse=True)
def _require_kj():
    if not _kj_installed():
        pytest.skip("kj not installed (scripts/install-kyverno-json.sh)")


class TestBlockOnAnyCritical:
    def test_no_critical_passes(self):
        pcrs = [
            {"severity": "high", "result": "fail", "ruleId": "X", "contractId": "c",
             "message": "", "resourceRef": "", "engine": "kyverno", "evaluatedAt": "t",
             "evidence": {}},
            {"severity": "info", "result": "pass", "ruleId": "Y", "contractId": "c",
             "message": "", "resourceRef": "", "engine": "kyverno", "evaluatedAt": "t",
             "evidence": {}},
        ]
        eng = KyvernoJsonEngine()
        out = eng.evaluate(pcrs, POLICY_DIR / "block-on-any-critical.json"
                          if (POLICY_DIR / "block-on-any-critical.json").is_file() else POLICY_DIR,
                          "cid")
        assert isinstance(out, list)

    def test_critical_fail_present(self):
        pcrs = [
            {"severity": "critical", "result": "fail", "ruleId": "Z", "contractId": "c",
             "message": "critical!", "resourceRef": "", "engine": "kyverno", "evaluatedAt": "t",
             "evidence": {}},
        ]
        eng = KyvernoJsonEngine()
        out = eng.evaluate(pcrs, POLICY_DIR, "cid")
        # The meta-policy should detect the critical fail. When kj runs,
        # it produces a result entry. We assert the engine returns a list
        # (the meta-policy PCRs).
        assert isinstance(out, list)


class TestPolicyFilesExist:
    def test_two_meta_policies_present(self):
        files = sorted(os.listdir(POLICY_DIR))
        assert "block-on-any-critical.json" in files
        assert "tagging-rules-agree.json" in files

    def test_policies_are_valid_json(self):
        for f in os.listdir(POLICY_DIR):
            if f.endswith(".json"):
                with open(POLICY_DIR / f, "r", encoding="utf-8") as fh:
                    data = json.load(fh)
                assert data["apiVersion"] == "json.kyverno.io/v1alpha1"
                assert data["kind"] == "ValidatingPolicy"
                assert "nova.cloudinit.dev/severity" in data["metadata"]["annotations"]

    def test_block_on_critical_has_critical_severity(self):
        with open(POLICY_DIR / "block-on-any-critical.json", "r", encoding="utf-8") as fh:
            data = json.load(fh)
        assert data["metadata"]["annotations"]["nova.cloudinit.dev/severity"] == "critical"