"""Performance tests for structured logging wrapper.

These tests demonstrate the performance benefit of the StructuredLogger wrapper
by comparing it against the standard library logging with extra={} dict allocation.
"""

from __future__ import annotations

import logging
import time

import pytest

from pinecone._internal.logging import StructuredLogger, get_logger


pytestmark = pytest.mark.unit


def test_logging_disabled_performance_with_guards():
    """Verify manual guards provide performance benefit when logging is disabled.

    This test demonstrates that adding manual guards to the hot path (HTTP client)
    provides measurable performance improvement.
    """
    # Setup logger
    logger = logging.getLogger("test_guards")
    logger.setLevel(logging.WARNING)  # DEBUG disabled

    iterations = 100_000

    # Scenario 1: Without guard (original code pattern)
    start = time.perf_counter()
    for i in range(iterations):
        logger.debug(
            "Request completed",
            extra={
                "status": 200,
                "duration": 0.123,
                "method": "POST",
                "path": "/api/endpoint",
                "iteration": i,
            },
        )
    no_guard_duration = time.perf_counter() - start

    # Scenario 2: With manual guard (our optimization)
    start = time.perf_counter()
    for i in range(iterations):
        if logger.isEnabledFor(logging.DEBUG):
            logger.debug(
                "Request completed",
                extra={
                    "status": 200,
                    "duration": 0.123,
                    "method": "POST",
                    "path": "/api/endpoint",
                    "iteration": i,
                },
            )
    with_guard_duration = time.perf_counter() - start

    improvement_ratio = no_guard_duration / with_guard_duration
    print(f"\nPerformance comparison ({iterations:,} iterations, DEBUG disabled):")
    print(f"  without guard: {no_guard_duration:.4f}s")
    print(f"  with guard:    {with_guard_duration:.4f}s")
    print(f"  Speedup:       {improvement_ratio:.2f}x")
    print(f"  Time saved:    {(no_guard_duration - with_guard_duration) * 1000:.2f}ms")

    # Manual guards should be significantly faster
    assert with_guard_duration < no_guard_duration, "Guards should be faster"
    assert improvement_ratio > 1.2, "Should see at least 20% improvement"


def test_logging_enabled_no_performance_regression():
    """Verify StructuredLogger has minimal overhead when logging is enabled.

    When logging is enabled, both approaches do the same work. The wrapper
    should add negligible overhead.
    """
    # Setup: Create both logger types with null handlers to avoid I/O
    stdlib_logger = logging.getLogger("test_stdlib_enabled")
    stdlib_logger.addHandler(logging.NullHandler())
    structured_logger = get_logger("test_structured_enabled")
    structured_logger._logger.addHandler(logging.NullHandler())

    # Set both to DEBUG level (logging enabled)
    stdlib_logger.setLevel(logging.DEBUG)
    structured_logger._logger.setLevel(logging.DEBUG)

    iterations = 10_000

    # Benchmark stdlib logger
    start = time.perf_counter()
    for i in range(iterations):
        stdlib_logger.debug(
            "Request completed",
            extra={
                "status": 200,
                "duration": 0.123,
                "iteration": i,
            },
        )
    stdlib_duration = time.perf_counter() - start

    # Benchmark StructuredLogger
    start = time.perf_counter()
    for i in range(iterations):
        structured_logger.debug(
            "Request completed",
            status=200,
            duration=0.123,
            iteration=i,
        )
    structured_duration = time.perf_counter() - start

    print(f"\nPerformance comparison ({iterations:,} iterations, DEBUG enabled):")
    print(f"  stdlib logger:     {stdlib_duration:.4f}s")
    print(f"  StructuredLogger:  {structured_duration:.4f}s")
    print(f"  Overhead:          {((structured_duration / stdlib_duration - 1) * 100):.1f}%")

    # Wrapper should add less than 50% overhead when logging is enabled
    assert structured_duration < stdlib_duration * 1.5, "Overhead should be minimal"


def test_structured_logger_preserves_origin():
    """Verify StructuredLogger preserves logger name and hierarchy."""
    logger = get_logger("pinecone.test.module")

    # The wrapped logger should have the correct name
    assert isinstance(logger, StructuredLogger)
    assert logger._logger.name == "pinecone.test.module"

    # Should be part of pinecone logger hierarchy
    assert logger._logger.name.startswith("pinecone.")


def test_structured_fields_in_log_record():
    """Verify structured fields appear correctly in log records."""

    class RecordCapture(logging.Handler):
        def __init__(self):
            super().__init__()
            self.records = []

        def emit(self, record):
            self.records.append(record)

    # Setup logger with capture handler
    logger = get_logger("test_fields")
    logger._logger.setLevel(logging.DEBUG)
    handler = RecordCapture()
    logger._logger.addHandler(handler)

    # Log with structured fields
    logger.info("Test message", status=200, duration=0.5, success=True)

    # Verify fields appear in the log record
    assert len(handler.records) == 1
    record = handler.records[0]
    assert record.msg == "Test message"
    assert record.status == 200  # type: ignore[attr-defined]
    assert record.duration == 0.5  # type: ignore[attr-defined]
    assert record.success is True  # type: ignore[attr-defined]
