"""Tests for qremotex.config — ExecutorConfig."""

import os
from unittest import mock


from qremotex.config import ExecutorConfig


class TestExecutorConfig:
    """Verify configuration loading and validation."""

    @mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "wss://gw.qraptor.io/ws/executor",
        "QRAPTOR_API_KEY": "qrx_prod_abc123def456ghi789jkl012mno345",
        "QRAPTOR_EXECUTOR_ID": "exec-001",
        "QRAPTOR_EXECUTOR_NAME": "gpu-worker",
        "CONCURRENCY": "10",
        "HEARTBEAT_SEC": "15",
        "LOG_LEVEL": "DEBUG",
    }, clear=False)
    def test_loads_from_env(self) -> None:
        cfg = ExecutorConfig()
        assert cfg.gateway_url == "wss://gw.qraptor.io/ws/executor"
        assert cfg.api_key == "qrx_prod_abc123def456ghi789jkl012mno345"
        assert cfg.executor_id == "exec-001"
        assert cfg.executor_name == "gpu-worker"
        assert cfg.concurrency == 10
        assert cfg.heartbeat_sec == 15
        assert cfg.log_level == "DEBUG"

    @mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "wss://gw.qraptor.io/ws/executor",
        "QRAPTOR_API_KEY": "qrx_prod_abc123",
    }, clear=False)
    def test_defaults(self) -> None:
        cfg = ExecutorConfig()
        assert cfg.concurrency == 25
        assert cfg.heartbeat_sec == 20
        assert cfg.exec_timeout_sec == 300
        assert cfg.max_script_size_kb == 512
        assert cfg.enable_system_tools is True
        assert cfg.enable_user_tools is True

    @mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "wss://gw.qraptor.io/ws/executor",
        "QRAPTOR_API_KEY": "qrx_prod_abc123",
    }, clear=False)
    def test_validate_ok(self) -> None:
        cfg = ExecutorConfig()
        assert cfg.validate() == []

    @mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "",
        "QRAPTOR_API_KEY": "",
    }, clear=False)
    def test_validate_missing_required(self) -> None:
        cfg = ExecutorConfig()
        errors = cfg.validate()
        assert any("QRAPTOR_GATEWAY_URL" in e for e in errors)
        assert any("QRAPTOR_API_KEY" in e for e in errors)

    @mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "http://bad-scheme",
        "QRAPTOR_API_KEY": "qrx_prod_abc123",
    }, clear=False)
    def test_validate_bad_scheme(self) -> None:
        cfg = ExecutorConfig()
        errors = cfg.validate()
        assert any("ws://" in e for e in errors)

    @mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "wss://gw.qraptor.io/ws/executor",
        "QRAPTOR_API_KEY": "qrx_prod_abc123",
        "CONCURRENCY": "0",
    }, clear=False)
    def test_validate_bad_concurrency(self) -> None:
        cfg = ExecutorConfig()
        errors = cfg.validate()
        assert any("CONCURRENCY" in e for e in errors)

    @mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "wss://gw.qraptor.io/ws/executor",
        "QRAPTOR_API_KEY": "qrx_prod_abc123",
    }, clear=False)
    def test_build_capabilities(self) -> None:
        cfg = ExecutorConfig()
        caps = cfg.build_capabilities()
        assert "python:execute:unrestricted" in caps
        assert "tools:system" in caps
        assert "file:transfer" in caps
        assert any(c.startswith("concurrency:") for c in caps)

    @mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "wss://gw.qraptor.io/ws/executor",
        "QRAPTOR_API_KEY": "qrx_prod_abc123",
    }, clear=False)
    def test_parse_api_key_id(self) -> None:
        cfg = ExecutorConfig()
        key_id = cfg.parse_api_key_id()
        assert key_id.startswith("ak_")
        assert len(key_id) == 15  # "ak_" + 12 hex chars

    @mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "wss://gw.qraptor.io/ws/executor",
        "QRAPTOR_API_KEY": "qrx_prod_abc123def456ghi789jkl012mno345",
    }, clear=False)
    def test_api_key_prefix_masked(self) -> None:
        cfg = ExecutorConfig()
        prefix = cfg.api_key_prefix()
        assert prefix.endswith("****")
        assert len(prefix) == 18  # 14 + "****"

    @mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "wss://gw.qraptor.io/ws/executor",
        "QRAPTOR_API_KEY": "qrx_prod_abc123",
        "LABELS": '{"region":"us-east-1","gpu":"a100"}',
    }, clear=False)
    def test_labels_json(self) -> None:
        cfg = ExecutorConfig()
        assert cfg.labels == {"region": "us-east-1", "gpu": "a100"}

    @mock.patch.dict(os.environ, {
        "QRAPTOR_GATEWAY_URL": "wss://gw.qraptor.io/ws/executor",
        "QRAPTOR_API_KEY": "qrx_prod_abc123",
        "LABELS": "not json",
    }, clear=False)
    def test_labels_invalid_json_falls_back(self) -> None:
        cfg = ExecutorConfig()
        assert cfg.labels == {}
