"""Tests for structured logger."""

import json
from io import StringIO
from unittest.mock import patch

from dvgateway.observability.logger import create_logger


class TestLogger:
    def test_info_level_filters_debug(self) -> None:
        """Info-level logger should not output debug messages."""
        logger = create_logger(level="info")
        with patch("sys.stdout", new_callable=StringIO) as mock_stdout:
            logger.debug({}, "debug message")
            assert mock_stdout.getvalue() == ""

    def test_info_outputs(self) -> None:
        """Info messages should be written to stdout."""
        logger = create_logger(level="info")
        with patch("sys.stdout", new_callable=StringIO) as mock_stdout:
            logger.info({"key": "val"}, "test message")
            output = mock_stdout.getvalue()
            entry = json.loads(output)
            assert entry["level"] == "info"
            assert entry["msg"] == "test message"
            assert entry["key"] == "val"

    def test_error_goes_to_stderr(self) -> None:
        """Error messages should be written to stderr."""
        logger = create_logger(level="info")
        with patch("sys.stderr", new_callable=StringIO) as mock_stderr:
            logger.error({"err": "test"}, "error message")
            output = mock_stderr.getvalue()
            entry = json.loads(output)
            assert entry["level"] == "error"

    def test_pii_redaction(self) -> None:
        """Sensitive fields should be redacted."""
        logger = create_logger(level="info", redact_pii=True)
        with patch("sys.stdout", new_callable=StringIO) as mock_stdout:
            logger.info({"caller": "01012345678", "session_id": "abc"}, "test")
            output = mock_stdout.getvalue()
            entry = json.loads(output)
            assert entry["caller"] == "[REDACTED]"
            assert entry["session_id"] == "abc"

    def test_pii_phone_pattern(self) -> None:
        """Phone numbers in string values should be masked."""
        logger = create_logger(level="info", redact_pii=True)
        with patch("sys.stdout", new_callable=StringIO) as mock_stdout:
            logger.info({"info": "User phone: 01098765432 called"}, "test")
            output = mock_stdout.getvalue()
            entry = json.loads(output)
            assert "01098765432" not in entry["info"]

    def test_no_redaction(self) -> None:
        """With redact_pii=False, fields should not be redacted."""
        logger = create_logger(level="info", redact_pii=False)
        with patch("sys.stdout", new_callable=StringIO) as mock_stdout:
            logger.info({"caller": "01012345678"}, "test")
            output = mock_stdout.getvalue()
            entry = json.loads(output)
            assert entry["caller"] == "01012345678"
