"""
Unit tests for visibe/__init__.py — init(), shutdown(), _detect_frameworks().

All tests use frameworks=[] to skip patching real packages.
No framework dependencies required.
"""
import sys
import pytest

import visibe
import visibe as _mod


# ---------------------------------------------------------------------------
# Fixture: reset global state around every test
# ---------------------------------------------------------------------------

@pytest.fixture(autouse=True)
def reset_visibe_globals():
    """Ensure clean global state before and after each test."""
    _mod._global_client = None
    _mod._auto_patched_frameworks.clear()
    yield
    _mod._global_client = None
    _mod._auto_patched_frameworks.clear()


# ---------------------------------------------------------------------------
# _detect_frameworks
# ---------------------------------------------------------------------------

def test_detect_frameworks_returns_dict():
    assert isinstance(visibe._detect_frameworks(), dict)


def test_detect_frameworks_has_all_expected_keys():
    keys = set(visibe._detect_frameworks().keys())
    assert keys == {"openai", "langchain", "langgraph", "crewai", "autogen", "bedrock"}


def test_detect_frameworks_values_are_bool():
    result = visibe._detect_frameworks()
    assert all(isinstance(v, bool) for v in result.values())


def test_detect_frameworks_false_for_blocked_module(monkeypatch):
    """Setting a module to None in sys.modules causes ImportError on import."""
    monkeypatch.setitem(sys.modules, "openai", None)
    result = visibe._detect_frameworks()
    assert result["openai"] is False


# ---------------------------------------------------------------------------
# init() — basic behavior
# ---------------------------------------------------------------------------

def test_init_returns_visibe_instance():
    client = visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])
    assert isinstance(client, visibe.Visibe)


def test_init_creates_global_client():
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])
    assert _mod._global_client is not None


def test_init_stores_api_key():
    client = visibe.init(api_key="sk_live_abc123", api_url="http://localhost:3000", frameworks=[])
    assert client.api_key == "sk_live_abc123"


def test_init_stores_api_url():
    client = visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])
    assert client.api_url == "http://localhost:3000"


def test_init_strips_trailing_slash_from_url():
    client = visibe.init(api_key="sk_live_test", api_url="http://localhost:3000/", frameworks=[])
    assert not client.api_url.endswith("/")


def test_init_double_call_returns_same_instance():
    c1 = visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])
    c2 = visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])
    assert c1 is c2


def test_init_empty_frameworks_patches_nothing():
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])
    assert _mod._auto_patched_frameworks == []


def test_init_unknown_framework_name_is_skipped():
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=["not_real"])
    assert _mod._auto_patched_frameworks == []


# ---------------------------------------------------------------------------
# init() — environment variable handling
# ---------------------------------------------------------------------------

def test_init_reads_api_key_from_env(monkeypatch):
    monkeypatch.setenv("VISIBE_API_KEY", "sk_live_from_env")
    monkeypatch.delenv("VISIBE_API_URL", raising=False)
    client = visibe.init(frameworks=[])
    assert client.api_key == "sk_live_from_env"


def test_init_content_limit_env_does_not_crash(monkeypatch):
    monkeypatch.setenv("VISIBE_CONTENT_LIMIT", "500")
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])


def test_init_invalid_content_limit_env_does_not_crash(monkeypatch):
    monkeypatch.setenv("VISIBE_CONTENT_LIMIT", "not-a-number")
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])


def test_init_auto_instrument_env_parses_comma_list(monkeypatch):
    """VISIBE_AUTO_INSTRUMENT=openai,langchain overrides framework auto-detect."""
    monkeypatch.setenv("VISIBE_AUTO_INSTRUMENT", "openai,langchain")
    # Neither is installed in CI — should complete without patching or crashing
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000")


def test_init_auto_instrument_env_all_uses_auto_detect(monkeypatch):
    """VISIBE_AUTO_INSTRUMENT=all falls through to auto-detect (same as default)."""
    monkeypatch.setenv("VISIBE_AUTO_INSTRUMENT", "all")
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])


def test_init_debug_env_does_not_crash(monkeypatch):
    monkeypatch.setenv("VISIBE_DEBUG", "1")
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])


def test_init_explicit_param_takes_precedence_over_env(monkeypatch):
    monkeypatch.setenv("VISIBE_API_KEY", "sk_live_from_env")
    client = visibe.init(api_key="sk_live_explicit", api_url="http://localhost:3000", frameworks=[])
    assert client.api_key == "sk_live_explicit"


# ---------------------------------------------------------------------------
# shutdown()
# ---------------------------------------------------------------------------

def test_shutdown_clears_global_client():
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])
    visibe.shutdown()
    assert _mod._global_client is None


def test_shutdown_clears_auto_patched_frameworks():
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])
    visibe.shutdown()
    assert _mod._auto_patched_frameworks == []


def test_shutdown_without_init_does_not_crash():
    visibe.shutdown()  # should be a no-op


def test_shutdown_idempotent():
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])
    visibe.shutdown()
    visibe.shutdown()  # second call should not raise


def test_reinit_after_shutdown_works():
    visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])
    visibe.shutdown()
    client = visibe.init(api_key="sk_live_test", api_url="http://localhost:3000", frameworks=[])
    assert isinstance(client, visibe.Visibe)
    assert _mod._global_client is not None
