import types
import pytest
import os
import json

from py_azpe import AzurePolicyEngine


class DummyModel:
    def __init__(self, **kwargs):
        self._data = kwargs

    def as_dict(self):
        return self._data


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

    def create(self, scope, name, params):
        # capture the type of params
        self.created.append((scope, name, params))
        # return an object with as_dict
        return types.SimpleNamespace(
            as_dict=lambda: {
                "scope": scope,
                "name": name,
                "params_type": type(params).__name__,
            }
        )


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


class DummyPolicyClientFactory:
    def __init__(self, client):
        self._client = client

    def __call__(self, credential, subscription):
        return self._client


def test_sdk_create_assignment_uses_model(monkeypatch, tmp_path):
    # Build engine with sdk backend
    engine = AzurePolicyEngine(backend="sdk", policy_dir=str(tmp_path))

    # Prepare dummy client and patch the import path
    dummy_client = DummyPolicyClient()

    # Mock PolicyClient factory in azure.mgmt.resource
    fake_pkg = types.SimpleNamespace(
        PolicyClient=DummyPolicyClientFactory(dummy_client)
    )
    monkeypatch.setitem(__import__("sys").modules, "azure.mgmt.resource", fake_pkg)

    # Also provide a dummy model class at azure.mgmt.resource.policy.models.PolicyAssignment
    policy_module = types.SimpleNamespace()
    policy_module.models = types.SimpleNamespace(PolicyAssignment=DummyModel)
    monkeypatch.setitem(
        __import__("sys").modules, "azure.mgmt.resource.policy", policy_module
    )

    # Create assignment dict
    assignment = {
        "properties": {
            "displayName": "TestAssign",
            "policyDefinitionId": "/subscriptions/x/providers/Microsoft.Authorization/policySetDefinitions/init1",
        }
    }

    res = engine.create_assignment("myAssign", assignment, scope="/subscriptions/x")
    assert res.get("name") == "myAssign" or res.get("params_type") in (
        "DummyModel",
        "dict",
    )


def test_sdk_deploy_initiative_uses_model(monkeypatch, tmp_path):
    engine = AzurePolicyEngine(backend="sdk", policy_dir=str(tmp_path))
    dummy_client = types.SimpleNamespace()

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

        def create_or_update(self, name, model):
            self.created.append((name, model))
            return types.SimpleNamespace(
                as_dict=lambda: {"name": name, "model_type": type(model).__name__}
            )

    dummy_client.policy_set_definitions = DummySetDefs()

    # Patch PolicyClient creation
    monkeypatch.setitem(
        __import__("sys").modules,
        "azure.mgmt.resource",
        types.SimpleNamespace(PolicyClient=lambda cred, sub: dummy_client),
    )
    # provide model class
    policy_module = types.SimpleNamespace()
    policy_module.models = types.SimpleNamespace(PolicySetDefinition=DummyModel)
    monkeypatch.setitem(
        __import__("sys").modules, "azure.mgmt.resource.policy", policy_module
    )

    initiative = {"properties": {"displayName": "MyInit", "policyDefinitions": []}}
    res = engine.deploy_initiative("init1", initiative)
    assert res.get("name") == "init1" or res.get("model_type") in ("DummyModel", "dict")
