"""Unit tests for the uvicorn logging configuration module.

Tests LOGGING_CONFIG dict and get_uvicorn_log_config from
src/infrastructure/logging/uvicorn_config.py.
"""

import logging
import logging.config

import pytest

from src.infrastructure.logging.uvicorn_config import (
    LOG_FILE,
    LOGGING_CONFIG,
    LOGS_DIR,
    get_uvicorn_log_config,
)


class TestLoggingConfigStructure:
    """Tests for the LOGGING_CONFIG dict schema."""

    def test_version_is_one(self):
        """Logging config version must be 1."""
        assert LOGGING_CONFIG["version"] == 1

    def test_disable_existing_loggers_false(self):
        """Existing loggers should not be disabled."""
        assert LOGGING_CONFIG["disable_existing_loggers"] is False

    def test_has_formatters_section(self):
        """Config contains formatters."""
        assert "formatters" in LOGGING_CONFIG
        assert len(LOGGING_CONFIG["formatters"]) >= 2

    def test_has_handlers_section(self):
        """Config contains handlers."""
        assert "handlers" in LOGGING_CONFIG
        assert "console" in LOGGING_CONFIG["handlers"]
        assert "file" in LOGGING_CONFIG["handlers"]

    def test_has_loggers_section(self):
        """Config contains logger definitions."""
        assert "loggers" in LOGGING_CONFIG

    def test_has_root_section(self):
        """Config has a root logger entry."""
        assert "root" in LOGGING_CONFIG
        assert "handlers" in LOGGING_CONFIG["root"]


class TestFormatters:
    """Tests for formatter definitions."""

    def test_default_formatter_exists(self):
        """Default formatter is defined."""
        assert "default" in LOGGING_CONFIG["formatters"]

    def test_access_formatter_exists(self):
        """Access formatter is defined."""
        assert "access" in LOGGING_CONFIG["formatters"]

    def test_detailed_formatter_exists(self):
        """Detailed formatter is defined for file output."""
        assert "detailed" in LOGGING_CONFIG["formatters"]

    def test_detailed_formatter_has_datefmt(self):
        """Detailed formatter includes date format."""
        assert "datefmt" in LOGGING_CONFIG["formatters"]["detailed"]


class TestHandlers:
    """Tests for handler definitions."""

    def test_console_handler_streams_to_stdout(self):
        """Console handler streams to stdout."""
        assert LOGGING_CONFIG["handlers"]["console"]["stream"] == "ext://sys.stdout"

    def test_file_handler_uses_detailed_formatter(self):
        """File handler uses the detailed formatter."""
        assert LOGGING_CONFIG["handlers"]["file"]["formatter"] == "detailed"

    def test_file_handler_encoding_is_utf8(self):
        """File handler writes UTF-8."""
        assert LOGGING_CONFIG["handlers"]["file"]["encoding"] == "utf-8"

    def test_file_handler_mode_is_append(self):
        """File handler appends to existing file."""
        assert LOGGING_CONFIG["handlers"]["file"]["mode"] == "a"


class TestLoggerDefinitions:
    """Tests for individual logger entries."""

    def test_uvicorn_logger_defined(self):
        """Main uvicorn logger is configured."""
        assert "uvicorn" in LOGGING_CONFIG["loggers"]

    def test_uvicorn_error_logger_defined(self):
        """uvicorn.error logger is configured."""
        assert "uvicorn.error" in LOGGING_CONFIG["loggers"]

    def test_uvicorn_access_logger_defined(self):
        """uvicorn.access logger is configured."""
        assert "uvicorn.access" in LOGGING_CONFIG["loggers"]

    def test_aniworld_logger_defined(self):
        """Application 'aniworld' logger is configured."""
        assert "aniworld" in LOGGING_CONFIG["loggers"]

    def test_watchfiles_logger_suppressed(self):
        """watchfiles.main logger level is WARNING to reduce noise."""
        wf = LOGGING_CONFIG["loggers"]["watchfiles.main"]
        assert wf["level"] == "WARNING"

    def test_uvicorn_loggers_no_propagation(self):
        """Uvicorn loggers do not propagate to root."""
        for name in ("uvicorn", "uvicorn.error", "uvicorn.access"):
            assert LOGGING_CONFIG["loggers"][name]["propagate"] is False

    def test_all_loggers_have_handlers(self):
        """Every logger definition specifies at least one handler."""
        for name, cfg in LOGGING_CONFIG["loggers"].items():
            assert "handlers" in cfg, f"Logger '{name}' missing handlers"
            assert len(cfg["handlers"]) >= 1


class TestPaths:
    """Tests for log path constants."""

    def test_logs_dir_is_path(self):
        """LOGS_DIR is a Path object."""
        from pathlib import Path
        assert isinstance(LOGS_DIR, Path)

    def test_log_file_is_path(self):
        """LOG_FILE is a Path object."""
        from pathlib import Path
        assert isinstance(LOG_FILE, Path)

    def test_log_file_parent_is_logs_dir(self):
        """LOG_FILE resides in LOGS_DIR."""
        assert LOG_FILE.parent == LOGS_DIR

    def test_log_file_name(self):
        """Default log file is fastapi_app.log."""
        assert LOG_FILE.name == "fastapi_app.log"


class TestGetUvicornLogConfig:
    """Tests for get_uvicorn_log_config function."""

    def test_returns_dict(self):
        """Returns a dictionary."""
        cfg = get_uvicorn_log_config()
        assert isinstance(cfg, dict)

    def test_returns_same_config(self):
        """Returns the module-level LOGGING_CONFIG constant."""
        assert get_uvicorn_log_config() is LOGGING_CONFIG

    def test_config_is_valid_for_dictconfig(self, tmp_path, monkeypatch):
        """Configuration is accepted by logging.config.dictConfig."""
        cfg = get_uvicorn_log_config()
        # Override the file handler filename to avoid side effects
        import copy
        test_cfg = copy.deepcopy(cfg)
        test_cfg["handlers"]["file"]["filename"] = str(tmp_path / "test.log")
        # Should not raise
        logging.config.dictConfig(test_cfg)
