"""host_dispatch：nonce 与环境变量 AICD_HOST_REQUIRE_NONCE（与 require_nonce 参数组合）。"""

from __future__ import annotations

import asyncio
from pathlib import Path
from types import SimpleNamespace

import pytest

from aicd.host_dispatch import (
    _coerce_host_bool_flag,
    dispatch_host_request,
)
from aicd.host_tokens import issue_host_nonce


def _ping_ctx() -> SimpleNamespace:
    return SimpleNamespace(invocation=None, plugin_registry=None)


@pytest.mark.parametrize(
    ("raw", "default", "expected"),
    [
        (None, True, True),
        (None, False, False),
        ("false", True, False),
        ("FALSE", True, False),
        (" true ", False, True),
        ("0", True, False),
        ("off", True, False),
        ("1", False, True),
        ("yes", False, True),
        (0, True, False),
        (1, False, True),
    ],
)
def test_coerce_host_bool_flag(raw, default, expected) -> None:
    assert _coerce_host_bool_flag(raw, default=default) is expected


def test_env_require_nonce_1_rejects_without_auth_even_if_param_false(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    """进程设 AICD_HOST_REQUIRE_NONCE=1 时，dispatch 仍校验 nonce（与 require_nonce 参数无关）。"""
    monkeypatch.setenv("AICD_HOST_REQUIRE_NONCE", "1")

    async def _go() -> None:
        resp = await dispatch_host_request(
            _ping_ctx(),
            {"id": "e1", "method": "ping", "params": {}},
            state_dir=tmp_path,
            require_nonce=False,
        )
        assert resp == {
            "ok": False,
            "id": "e1",
            "error": "auth.nonce required",
            "code": "auth",
        }

    asyncio.run(_go())


def test_env_require_nonce_1_accepts_valid_nonce_with_require_nonce_false(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    monkeypatch.setenv("AICD_HOST_REQUIRE_NONCE", "1")
    tok = issue_host_nonce(tmp_path, ttl_sec=600)

    async def _go() -> None:
        resp = await dispatch_host_request(
            _ping_ctx(),
            {
                "id": "e2",
                "method": "ping",
                "params": {},
                "auth": {"nonce": tok},
            },
            state_dir=tmp_path,
            require_nonce=False,
        )
        assert resp["ok"] is True
        assert resp["id"] == "e2"
        assert resp["result"]["pong"] is True

    asyncio.run(_go())
