"""Tests for ievo.core.telemetry — Sentry opt-in."""

from __future__ import annotations

from pathlib import Path
from unittest.mock import MagicMock, patch

from ievo.core.global_config import get_config, load_global_config, set_config
from ievo.core.telemetry import (
    CLI_SENTRY_DSN,
    init_sentry,
    is_telemetry_enabled,
    prompt_telemetry,
    reset_sentry_state,
)

# ── is_telemetry_enabled ─────────────────────────────────────


def test_is_telemetry_enabled_true(tmp_path: Path) -> None:
    load_global_config(tmp_path)
    set_config(tmp_path, "telemetry", True)
    assert is_telemetry_enabled(tmp_path) is True


def test_is_telemetry_enabled_false(tmp_path: Path) -> None:
    load_global_config(tmp_path)
    set_config(tmp_path, "telemetry", False)
    assert is_telemetry_enabled(tmp_path) is False


def test_is_telemetry_enabled_none(tmp_path: Path) -> None:
    load_global_config(tmp_path)
    assert is_telemetry_enabled(tmp_path) is False


# ── prompt_telemetry ──────────────────────────────────────────


def test_prompt_telemetry_yes(tmp_path: Path) -> None:
    load_global_config(tmp_path)
    with patch("builtins.input", return_value="y"):
        result = prompt_telemetry(tmp_path)
    assert result is True
    assert get_config(tmp_path, "telemetry") is True


def test_prompt_telemetry_yes_full(tmp_path: Path) -> None:
    load_global_config(tmp_path)
    with patch("builtins.input", return_value="yes"):
        result = prompt_telemetry(tmp_path)
    assert result is True


def test_prompt_telemetry_no(tmp_path: Path) -> None:
    load_global_config(tmp_path)
    with patch("builtins.input", return_value="n"):
        result = prompt_telemetry(tmp_path)
    assert result is False
    assert get_config(tmp_path, "telemetry") is False


def test_prompt_telemetry_empty_means_no(tmp_path: Path) -> None:
    load_global_config(tmp_path)
    with patch("builtins.input", return_value=""):
        result = prompt_telemetry(tmp_path)
    assert result is False


# ── init_sentry ───────────────────────────────────────────────


def test_init_sentry_enabled(tmp_path: Path) -> None:
    reset_sentry_state()
    load_global_config(tmp_path)
    set_config(tmp_path, "telemetry", True)

    mock_sdk = MagicMock()
    with patch.dict("sys.modules", {"sentry_sdk": mock_sdk}):
        result = init_sentry(tmp_path)
    assert result is True
    mock_sdk.init.assert_called_once()
    call_kwargs = mock_sdk.init.call_args[1]
    assert call_kwargs["dsn"] == CLI_SENTRY_DSN
    assert call_kwargs["environment"] == "cli"
    assert call_kwargs["send_default_pii"] is False


def test_init_sentry_disabled(tmp_path: Path) -> None:
    reset_sentry_state()
    load_global_config(tmp_path)
    set_config(tmp_path, "telemetry", False)
    assert init_sentry(tmp_path) is False


def test_init_sentry_not_asked(tmp_path: Path) -> None:
    reset_sentry_state()
    load_global_config(tmp_path)
    assert init_sentry(tmp_path) is False


def test_init_sentry_no_sdk(tmp_path: Path) -> None:
    reset_sentry_state()
    load_global_config(tmp_path)
    set_config(tmp_path, "telemetry", True)

    with patch.dict("sys.modules", {"sentry_sdk": None}):
        result = init_sentry(tmp_path)
    assert result is False


def test_init_sentry_idempotent(tmp_path: Path) -> None:
    reset_sentry_state()
    load_global_config(tmp_path)
    set_config(tmp_path, "telemetry", True)

    mock_sdk = MagicMock()
    with patch.dict("sys.modules", {"sentry_sdk": mock_sdk}):
        init_sentry(tmp_path)
        init_sentry(tmp_path)
    # Only called once despite two calls
    mock_sdk.init.assert_called_once()


# ── reset_sentry_state ────────────────────────────────────────


def test_reset_sentry_state(tmp_path: Path) -> None:
    reset_sentry_state()
    load_global_config(tmp_path)
    set_config(tmp_path, "telemetry", True)

    mock_sdk = MagicMock()
    with patch.dict("sys.modules", {"sentry_sdk": mock_sdk}):
        init_sentry(tmp_path)
        reset_sentry_state()
        init_sentry(tmp_path)
    # Called twice because state was reset
    assert mock_sdk.init.call_count == 2


# ── DSN constant ──────────────────────────────────────────────


def test_sentry_dsn_format() -> None:
    assert CLI_SENTRY_DSN.startswith("https://")
    assert "sentry.io" in CLI_SENTRY_DSN
