"""Tests for quber.utils.logging module."""

import logging
import os
from pathlib import Path
from typing import TYPE_CHECKING
from unittest.mock import MagicMock, patch

import pytest
from loguru import logger

from quber.settings import get_settings
from quber.utils.logging import get_logger, setup_logging

if TYPE_CHECKING:
    from unittest.mock import MagicMock as MagicMockType


@pytest.fixture(autouse=True)
def isolate_settings(monkeypatch: pytest.MonkeyPatch, tmp_path: Path):
    # setup_logging now reads get_settings().obs.logfire_token; clear the cache
    # and chdir to an empty dir so each test sees only its patched os.environ
    # (no leftover cache, no real .env token leaking in).
    monkeypatch.chdir(tmp_path)
    get_settings.cache_clear()
    yield
    get_settings.cache_clear()


def test_setup_logging_basic():
    """Test basic logging setup without logfire."""
    with patch.dict(os.environ, {}, clear=True):
        setup_logging(enable_logfire=False)

    assert logger


def test_setup_logging_custom_log_level():
    """Test setup_logging with custom log level."""
    with patch.dict(os.environ, {}, clear=True):
        setup_logging(log_level="DEBUG", enable_logfire=False)

    assert logger


def test_setup_logging_suppress_external():
    """Test that external library loggers are suppressed."""
    with patch.dict(os.environ, {}, clear=True):
        setup_logging(suppress_external=True, enable_logfire=False)

    assert logging.getLogger("docling").level == logging.WARNING
    assert logging.getLogger("httpx").level == logging.WARNING
    assert logging.getLogger("anthropic").level == logging.WARNING


def test_setup_logging_no_suppress_external():
    """Test logging without suppressing external libraries."""
    with patch.dict(os.environ, {}, clear=True):
        logging.getLogger("docling").setLevel(logging.INFO)

        setup_logging(suppress_external=False, enable_logfire=False)

        assert logging.getLogger("docling").level == logging.INFO


@patch("quber.utils.logging.logfire")
@patch.dict(os.environ, {"PYDANTIC_LOGFIRE_TOKEN": "test-token"})
def test_setup_logging_with_logfire_token(mock_logfire: "MagicMockType"):
    """Test logfire setup when token is available."""
    mock_logfire.configure = MagicMock()
    mock_logfire.instrument_anthropic = MagicMock()
    mock_logfire.instrument_openai = MagicMock()
    mock_logfire.instrument_pydantic_ai = MagicMock()

    setup_logging(enable_logfire=True, log_level="INFO")

    mock_logfire.configure.assert_called_once_with(
        service_name="quber",
        token="test-token",
        console=False,
    )
    mock_logfire.instrument_anthropic.assert_called_once()
    mock_logfire.instrument_openai.assert_called_once()
    mock_logfire.instrument_pydantic_ai.assert_called_once()


@patch("quber.utils.logging.logfire")
@patch.dict(os.environ, {"PYDANTIC_LOGFIRE_TOKEN": "test-token"})
def test_setup_logging_with_logfire_debug_mode(mock_logfire: "MagicMockType"):
    """Test logfire debug logging."""
    mock_logfire.configure = MagicMock()
    mock_logfire.instrument_anthropic = MagicMock()
    mock_logfire.instrument_openai = MagicMock()
    mock_logfire.instrument_pydantic_ai = MagicMock()

    setup_logging(enable_logfire=True, log_level="DEBUG")

    mock_logfire.configure.assert_called_once()


@patch("quber.utils.logging.logfire")
@patch.dict(os.environ, {}, clear=True)
def test_setup_logging_without_logfire_token(mock_logfire: "MagicMockType"):
    """Test that logfire is not configured without token."""
    mock_logfire.configure = MagicMock()

    setup_logging(enable_logfire=True)

    mock_logfire.configure.assert_not_called()


@patch("quber.utils.logging.logfire")
@patch.dict(os.environ, {"PYDANTIC_LOGFIRE_TOKEN": "test-token"})
def test_setup_logging_logfire_exception(mock_logfire: "MagicMockType"):
    """Test handling of logfire configuration exception."""
    mock_logfire.configure.side_effect = Exception("Logfire error")

    setup_logging(enable_logfire=True)


def test_setup_logging_custom_service_name():
    """Test setup_logging with custom service name."""
    with patch.dict(os.environ, {}, clear=True):
        setup_logging(service_name="custom-service", enable_logfire=False)

    assert logger


def test_get_logger_without_name():
    """Test getting logger without custom name."""
    log = get_logger()

    assert log is not None
    assert hasattr(log, "info")
    assert hasattr(log, "debug")
    assert hasattr(log, "warning")
    assert hasattr(log, "error")


def test_get_logger_with_name():
    """Test getting logger with custom name."""
    log = get_logger("test-context")

    assert log is not None
    assert hasattr(log, "info")


def test_get_logger_returns_loguru_instance():
    """Test that get_logger returns a loguru logger instance."""
    log = get_logger()

    assert hasattr(log, "bind")
    assert hasattr(log, "opt")
    assert hasattr(log, "catch")


def test_setup_logging_multiple_calls():
    """Test that setup_logging can be called multiple times."""
    with patch.dict(os.environ, {}, clear=True):
        setup_logging(log_level="INFO", enable_logfire=False)
        setup_logging(log_level="DEBUG", enable_logfire=False)

    assert logger
