import json

import pytest

from eda_agent.engine import EDAEngine
from eda_agent.services.normbase_client import MockNormbaseClient
from eda_agent.state import EDAState, ValueWeight
from llm.providers import BaseLLMProvider


class FakeLLMProvider(BaseLLMProvider):
    async def chat(self, messages, **kwargs):
        del messages, kwargs
        return json.dumps(
            [
                {
                    "id": "p1",
                    "content": "user_intent=download_report",
                    "confidence": 0.85,
                    "source": "perception",
                    "norm_refs": [],
                }
            ]
        )

    async def structured_output(self, messages, schema):
        del messages, schema
        return {}

    async def async_get_embedding(self, text):
        del text
        return [0.1, 0.2, 0.3]


@pytest.mark.asyncio
async def test_eda_initialize_and_bind_norms():
    norms = [
        {
            "id": "n1",
            "type": "obligation",
            "scope_roles": ["analyst"],
            "status": "active",
            "condition": {"trigger": "requires_report"},
            "action": {"required": "mask_pii"},
            "consequence": {"on_violation": {"boundary": "soft"}},
            "formatted_prompt": "NORM[n1]: Must mask pii before export.",
        }
    ]
    engine = EDAEngine(MockNormbaseClient(norms=norms), FakeLLMProvider())
    state = await engine.initialize(
        agent_id="a1",
        agent_role="analyst",
        value_config=[ValueWeight("compliance", 0.9, 1, "must")],
        active_fields=["f1"],
    )

    updated = await engine.bind_norms(state, {"requires_report": True})
    assert updated.agent_id == "a1"
    assert len(updated.norm_bindings) >= 1
    assert engine.last_bind_debug.get("formatted_prompt_used", 0) >= 1


@pytest.mark.asyncio
async def test_eda_compliance_boundary_and_value_ranking():
    engine = EDAEngine(MockNormbaseClient(norms=[]), FakeLLMProvider())
    state = EDAState(
        agent_id="a2",
        agent_role="reviewer",
        value_weights=[
            ValueWeight("safety", 0.8, 1, "high"),
            ValueWeight("speed", 0.2, 2, "low"),
        ],
    )
    action_candidates = [
        {"name": "safe", "value_satisfactions": {"safety": 1.0, "speed": 0.2}},
        {"name": "fast", "value_satisfactions": {"safety": 0.1, "speed": 1.0}},
    ]
    ranking = await engine.rank_values(state, action_candidates)
    assert ranking[0]["action"]["name"] == "safe"
    assert "explanation" in ranking[0]

