"""Tests for vcti.logging.custom_level and vcti.logging.log_level modules."""

import logging

from vcti.logging.custom_level import (
    CustomLevelLogger,
    CustomLogLevel,
)
from vcti.logging.log_level import (
    DEFAULT_LOG_LEVEL_STR,
    LogLevel,
    decode_log_level,
    encode_log_level,
)


class TestCustomLogLevel:
    def test_trace_value(self):
        assert CustomLogLevel.TRACE == 5

    def test_verbose_value(self):
        assert CustomLogLevel.VERBOSE == 15

    def test_trace_below_debug(self):
        assert CustomLogLevel.TRACE < logging.DEBUG

    def test_verbose_between_debug_and_info(self):
        assert logging.DEBUG < CustomLogLevel.VERBOSE < logging.INFO


class TestCustomLevelLogger:
    def test_get_logger_returns_custom_class(self):
        logger = logging.getLogger("test.custom_class")
        assert isinstance(logger, CustomLevelLogger)

    def test_has_trace_method(self):
        logger = logging.getLogger("test.trace")
        assert hasattr(logger, "trace")
        assert callable(logger.trace)

    def test_has_verbose_method(self):
        logger = logging.getLogger("test.verbose")
        assert hasattr(logger, "verbose")
        assert callable(logger.verbose)

    def test_trace_logs_at_correct_level(self, capfd):
        logger = logging.getLogger("test.trace.log")
        handler = logging.StreamHandler()
        handler.setLevel(1)
        logger.addHandler(handler)
        logger.setLevel(1)
        logger.trace("trace message")
        captured = capfd.readouterr()
        assert "trace message" in captured.err


class TestLogLevel:
    def test_includes_standard_levels(self):
        names = [level.name for level in LogLevel]
        assert "NOTSET" in names
        assert "DEBUG" in names
        assert "INFO" in names
        assert "WARNING" in names
        assert "ERROR" in names
        assert "FATAL" in names

    def test_includes_custom_levels(self):
        names = [level.name for level in LogLevel]
        assert "TRACE" in names
        assert "VERBOSE" in names

    def test_standard_level_values(self):
        assert LogLevel.NOTSET == logging.NOTSET
        assert LogLevel.DEBUG == logging.DEBUG
        assert LogLevel.INFO == logging.INFO
        assert LogLevel.WARNING == logging.WARNING
        assert LogLevel.ERROR == logging.ERROR
        assert LogLevel.FATAL == logging.FATAL

    def test_custom_level_values_match(self):
        assert LogLevel.TRACE == CustomLogLevel.TRACE
        assert LogLevel.VERBOSE == CustomLogLevel.VERBOSE

    def test_level_ordering(self):
        assert LogLevel.NOTSET < LogLevel.TRACE < LogLevel.DEBUG
        assert LogLevel.DEBUG < LogLevel.VERBOSE < LogLevel.INFO
        assert LogLevel.INFO < LogLevel.WARNING < LogLevel.ERROR < LogLevel.FATAL


class TestLogLevelEncoding:
    def test_default_is_info(self):
        assert DEFAULT_LOG_LEVEL_STR == "info"

    def test_decode_info(self):
        level = decode_log_level("info")
        assert level.value == logging.INFO

    def test_decode_fatal(self):
        level = decode_log_level("fatal")
        assert level.value == logging.FATAL

    def test_decode_case_insensitive(self):
        assert decode_log_level("INFO") == decode_log_level("info")
        assert decode_log_level("Fatal") == decode_log_level("fatal")
        assert decode_log_level("DEBUG") == decode_log_level("debug")

    def test_decode_invalid_raises_value_error(self):
        import pytest

        with pytest.raises(ValueError, match="not a valid log level"):
            decode_log_level("invalid")

    def test_encode_decode_roundtrip(self):
        for level in LogLevel:
            encoded = encode_log_level(level)
            decoded = decode_log_level(encoded)
            assert decoded == level
