from brox.diff.diff import compute_diff, parse_capability_record


class TestParseCapabilityRecord:
    def test_parse_json_format(self):
        record = '{"asset":"mcp_server:fs","cap":"filesystem.read","evidence":["a.py:10"],"scope":"/data/**"}'

        cap = parse_capability_record(record)

        assert cap is not None
        assert cap.name == "filesystem.read"
        assert cap.scope == "/data/**"
        assert cap.asset == "mcp_server:fs"
        assert cap.evidence == ["a.py:10"]

    def test_parse_legacy_format(self):
        record = "cap=filesystem.read;scope=/data/**;evidence=a.py:10;asset=mcp_server:fs"

        cap = parse_capability_record(record)

        assert cap is not None
        assert cap.name == "filesystem.read"
        assert cap.scope == "/data/**"
        assert cap.asset == "mcp_server:fs"

    def test_parse_invalid_returns_none(self):
        cap = parse_capability_record("invalid json")
        assert cap is None

        cap = parse_capability_record("")
        assert cap is None


class TestComputeDiff:
    def test_detect_added_components(self):
        base_bom = {
            "metadata": {"properties": [{"name": "brox.bom.hash", "value": "hash1"}]},
            "components": [{"bom-ref": "repo:root", "properties": []}],
        }

        head_bom = {
            "metadata": {"properties": [{"name": "brox.bom.hash", "value": "hash2"}]},
            "components": [
                {"bom-ref": "repo:root", "properties": []},
                {
                    "bom-ref": "mcp_server:fs",
                    "properties": [{"name": "brox.ai.asset.kind", "value": "mcp_server"}],
                },
            ],
        }

        diff = compute_diff(base_bom, head_bom)

        assert len(diff.assets_added) == 1
        assert diff.assets_added[0].id == "mcp_server:fs"
        assert diff.assets_added[0].kind == "mcp_server"

    def test_detect_removed_components(self):
        base_bom = {
            "metadata": {"properties": [{"name": "brox.bom.hash", "value": "hash1"}]},
            "components": [
                {"bom-ref": "repo:root", "properties": []},
                {
                    "bom-ref": "mcp_server:fs",
                    "properties": [{"name": "brox.ai.asset.kind", "value": "mcp_server"}],
                },
            ],
        }

        head_bom = {
            "metadata": {"properties": [{"name": "brox.bom.hash", "value": "hash2"}]},
            "components": [{"bom-ref": "repo:root", "properties": []}],
        }

        diff = compute_diff(base_bom, head_bom)

        assert len(diff.assets_removed) == 1
        assert diff.assets_removed[0].id == "mcp_server:fs"

    def test_detect_added_capabilities(self):
        base_bom = {
            "metadata": {"properties": []},
            "components": [],
            "services": [],
        }

        head_bom = {
            "metadata": {"properties": []},
            "components": [],
            "services": [
                {
                    "name": "brox.ai.capabilities",
                    "properties": [
                        {
                            "name": "brox.capability.record",
                            "value": '{"asset":"mcp_server:fs","cap":"filesystem.write","evidence":["mcp.json:10"],"scope":"/data/**"}',
                        }
                    ],
                }
            ],
        }

        diff = compute_diff(base_bom, head_bom)

        assert len(diff.capabilities_added) == 1
        assert diff.capabilities_added[0].capability == "filesystem.write"
        assert diff.capabilities_added[0].scope == "/data/**"

    def test_risk_assessment_included(self):
        base_bom = {"metadata": {"properties": []}, "components": [], "services": []}

        head_bom = {
            "metadata": {"properties": []},
            "components": [
                {
                    "bom-ref": "mcp_server:shell",
                    "properties": [{"name": "brox.ai.asset.kind", "value": "mcp_server"}],
                }
            ],
            "services": [
                {
                    "name": "brox.ai.capabilities",
                    "properties": [
                        {
                            "name": "brox.capability.record",
                            "value": '{"asset":"mcp_server:shell","cap":"exec.shell","evidence":["mcp.json:10"],"scope":"*"}',
                        }
                    ],
                }
            ],
        }

        diff = compute_diff(base_bom, head_bom)

        # exec.shell should trigger high risk
        assert diff.risk.level in ["high", "critical"]
        assert any("shell" in reason.lower() for reason in diff.risk.reasons)
