import types
import pytest

from py_azpe import AzurePolicyEngine


class DummyAssignmentsClient:
    def __init__(self):
        self.created = []

    def create(self, scope, name, params):
        self.created.append((scope, name, params))
        return types.SimpleNamespace(
            as_dict=lambda: {
                "scope": scope,
                "name": name,
                "params_type": type(params).__name__,
            }
        )


class DummyPolicyClient:
    def __init__(self):
        self.policy_assignments = DummyAssignmentsClient()


def _patch_policy_client(monkeypatch, dummy):
    monkeypatch.setitem(
        __import__("sys").modules,
        "azure.mgmt.resource",
        types.SimpleNamespace(PolicyClient=lambda cred, sub: dummy),
    )


def test_prepare_assignment_payload_returns_expected(monkeypatch, tmp_path):
    engine = AzurePolicyEngine(backend="sdk", policy_dir=str(tmp_path))
    # no SDK present -> prepare should still produce payload
    assign = {
        "properties": {
            "displayName": "DRY",
            "policyDefinitionId": "/subscriptions/0000/providers/Microsoft.Authorization/policyDefinitions/pd1",
        }
    }
    res = engine.prepare_assignment_payload("dry1", assign, scope="/subscriptions/0000")
    assert res["name"] == "dry1"
    assert res["scope"] == "/subscriptions/0000"
    assert "payload" in res


def test_validate_scope_rejects_bad(monkeypatch):
    engine = AzurePolicyEngine(backend="file")
    with pytest.raises(ValueError):
        engine._validate_scope("not-a-scope")
    with pytest.raises(ValueError):
        engine._validate_scope("")


def test_dry_run_with_mgmt_group(monkeypatch, tmp_path):
    engine = AzurePolicyEngine(backend="sdk", policy_dir=str(tmp_path))
    dummy = DummyPolicyClient()
    _patch_policy_client(monkeypatch, dummy)

    assign = {
        "properties": {
            "displayName": "MG DRY",
            "policyDefinitionId": "/providers/Microsoft.Management/managementGroups/mg1/providers/Microsoft.Authorization/policyDefinitions/pd1",
        }
    }
    res = engine.prepare_assignment_payload(
        "mgDry", assign, scope="/providers/Microsoft.Management/managementGroups/mg1"
    )
    assert res["scope"].endswith("mg1")
    assert res["name"] == "mgDry"
