"""Tests for qremotex.connection.auth — AuthManager."""

import hashlib
import hmac
import os
import time
from unittest import mock


from qremotex.config import ExecutorConfig
from qremotex.connection.auth import AuthManager

API_KEY = "qrx_prod_abc123def456ghi789jkl012mno345"


def _make_config() -> ExecutorConfig:
    with mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "wss://gw.qraptor.io/ws/executor",
        "QRAPTOR_API_KEY": API_KEY,
        "QRAPTOR_EXECUTOR_ID": "exec-test",
    }):
        return ExecutorConfig()


class TestAuthManager:

    def test_key_id(self) -> None:
        cfg = _make_config()
        auth = AuthManager(cfg)
        assert auth.key_id.startswith("ak_")
        assert len(auth.key_id) == 15

    def test_handshake_params(self) -> None:
        cfg = _make_config()
        auth = AuthManager(cfg)
        params = auth.handshake_params()
        assert "key_id" in params
        assert params["key_id"] == auth.key_id

    def test_handshake_headers_signature(self) -> None:
        cfg = _make_config()
        auth = AuthManager(cfg)
        headers = auth.handshake_headers()
        assert "X-QRP-Signature" in headers
        assert "X-QRP-Timestamp" in headers
        assert "X-QRP-Nonce" in headers
        assert headers["X-QRP-Signature"].startswith("sha256=")

    def test_handshake_signature_verifiable(self) -> None:
        cfg = _make_config()
        auth = AuthManager(cfg)
        headers = auth.handshake_headers()

        ts = headers["X-QRP-Timestamp"]
        nonce = headers["X-QRP-Nonce"]
        sig = headers["X-QRP-Signature"].replace("sha256=", "")

        # Re-compute and verify
        payload = f"{ts}.{nonce}.{auth.key_id}"
        expected = hmac.new(
            API_KEY.encode("utf-8"), payload.encode("utf-8"), hashlib.sha256
        ).hexdigest()
        assert sig == expected

    def test_sign_message(self) -> None:
        cfg = _make_config()
        auth = AuthManager(cfg)
        body = '{"type":"heartbeat","ts":1234}'
        headers = auth.sign_message(body)
        assert headers["X-QRP-Signature"].startswith("sha256=")

        # Verify
        ts = headers["X-QRP-Timestamp"]
        nonce = headers["X-QRP-Nonce"]
        sig = headers["X-QRP-Signature"].replace("sha256=", "")
        payload = f"{ts}.{nonce}.{body}"
        expected = hmac.new(
            API_KEY.encode("utf-8"), payload.encode("utf-8"), hashlib.sha256
        ).hexdigest()
        assert sig == expected

    def test_sign_dict_embeds_hmac_fields(self) -> None:
        cfg = _make_config()
        auth = AuthManager(cfg)
        msg = {"type": "heartbeat", "ts": 1234}
        signed = auth.sign_dict(msg)
        assert "_hmac_signature" in signed
        assert "_hmac_timestamp" in signed
        assert "_hmac_nonce" in signed
        assert signed["_hmac_signature"].startswith("sha256=")

    def test_timestamp_is_recent(self) -> None:
        cfg = _make_config()
        auth = AuthManager(cfg)
        headers = auth.handshake_headers()
        ts = int(headers["X-QRP-Timestamp"])
        now = int(time.time())
        assert abs(now - ts) < 5  # Within 5 seconds

    def test_nonce_uniqueness(self) -> None:
        cfg = _make_config()
        auth = AuthManager(cfg)
        nonces = {auth.handshake_headers()["X-QRP-Nonce"] for _ in range(100)}
        assert len(nonces) == 100  # All unique
