from acl_engine.engine import ACLEngine, execute_acl


def test_engine_executes_variable_chaining(tmp_path) -> None:
    engine = ACLEngine(workspace=tmp_path)
    acl_text = '\n'.join(
        [
            'util.echo(value="hello") -> greeting',
            'util.echo(value=greeting) -> copy',
        ]
    )

    result = engine.execute(acl_text)

    assert result["status"] == "success"
    assert result["data"]["greeting"] == "hello"
    assert result["data"]["copy"] == "hello"


def test_engine_supports_custom_action_registration(tmp_path) -> None:
    engine = ACLEngine(workspace=tmp_path)

    def db_query(sql: str) -> dict[str, str]:
        return {"sql": sql}

    engine.register_action("db.query", db_query, {"sql": str})
    result = engine.execute('db.query(sql="SELECT 1") -> result')

    assert result["status"] == "success"
    assert result["data"]["result"] == {"sql": "SELECT 1"}


def test_execute_acl_returns_parse_errors_as_structured_output(tmp_path) -> None:
    result = execute_acl('file.read(path="main.py"', workspace=tmp_path)

    assert result["status"] == "error"
    assert result["error"]["type"] == "ACLParseError"
    assert result["error"]["code"] == "parse_error"


def test_engine_supports_object_literals_and_selectors(tmp_path) -> None:
    engine = ACLEngine(workspace=tmp_path)
    acl_text = "\n".join(
        [
            'util.echo(value={message="hello", items=["a", "b"]}) -> payload',
            'util.echo(value=payload.message) -> message',
            'util.echo(value=payload.items[1]) -> second',
        ]
    )

    result = engine.execute(acl_text)

    assert result["status"] == "success"
    assert result["data"]["message"] == "hello"
    assert result["data"]["second"] == "b"


def test_engine_validate_and_dry_run(tmp_path) -> None:
    engine = ACLEngine(workspace=tmp_path)

    validate_result = engine.validate('util.echo(value="hello") -> msg')
    dry_run_result = engine.dry_run('util.echo(value="hello") -> msg')

    assert validate_result["status"] == "success"
    assert validate_result["data"]["commands"] == 1
    assert dry_run_result["status"] == "success"
    assert dry_run_result["data"]["plan"][0]["action"] == "util.echo"


def test_engine_validate_fails_for_missing_reference(tmp_path) -> None:
    engine = ACLEngine(workspace=tmp_path)

    result = engine.validate('util.echo(value=missing.value) -> msg')

    assert result["status"] == "error"
    assert result["error"]["type"] == "ACLVariableError"


def test_engine_output_includes_contract_metadata(tmp_path) -> None:
    engine = ACLEngine(workspace=tmp_path, trace_id="trace-123")

    result = engine.execute('util.echo(value="hello") -> msg')

    assert result["acl_version"] == "1.0"
    assert result["output_version"] == "1.2"
    assert result["trace_id"] == "trace-123"
    assert result["summary"]["policy"] == "standard"
    assert result["summary"]["steps_completed"] == 1
