"""Tests for the is_42 package — comprehensive integration tests."""

import decimal
import fractions
import pytest

from is_42 import is_42, why_42


# ========== Numeric ==========

class TestNumeric:
    def test_int_42(self):
        assert is_42(42) is True

    def test_int_not_42(self):
        assert is_42(43) is False
        assert is_42(0) is False
        assert is_42(-42) is False

    def test_float_42(self):
        assert is_42(42.0) is True

    def test_float_not_42(self):
        assert is_42(42.1) is False

    def test_complex_42(self):
        assert is_42(42 + 0j) is True

    def test_complex_not_42(self):
        assert is_42(42 + 1j) is False

    def test_decimal_42(self):
        assert is_42(decimal.Decimal("42")) is True
        assert is_42(decimal.Decimal("42.0")) is True

    def test_decimal_not_42(self):
        assert is_42(decimal.Decimal("43")) is False

    def test_fraction_42(self):
        assert is_42(fractions.Fraction(84, 2)) is True
        assert is_42(fractions.Fraction(42, 1)) is True

    def test_fraction_not_42(self):
        assert is_42(fractions.Fraction(43, 1)) is False

    def test_bool_not_42(self):
        # bool is subclass of int, True=1, False=0, neither is 42
        assert is_42(True) is False
        assert is_42(False) is False

    def test_none(self):
        assert is_42(None) is False

    def test_string_42(self):
        assert is_42("42") is True


# ========== Multilingual ==========

class TestMultilingual:
    def test_chinese(self):
        assert is_42("四十二") is True
        assert is_42("四二") is True
        assert is_42("肆拾贰") is True
        assert is_42("四十又二") is True

    def test_leiwanting(self):
        assert is_42("莱万汀") is True
        result = why_42("莱万汀")
        assert result is not None
        assert "莱万汀" in result

    def test_english(self):
        assert is_42("forty-two") is True
        assert is_42("Forty Two") is True
        assert is_42("FORTY-TWO") is True
        assert is_42("four two") is True
        assert is_42("FOUR TWO") is True
        assert is_42("fourty-two") is True  # common misspelling

    def test_french(self):
        assert is_42("quarante-deux") is True

    def test_german(self):
        assert is_42("zweiundvierzig") is True

    def test_spanish(self):
        assert is_42("cuarenta y dos") is True

    def test_japanese(self):
        assert is_42("よんじゅうに") is True

    def test_korean(self):
        assert is_42("사십이") is True
        assert is_42("마흔둘") is True

    def test_russian(self):
        assert is_42("сорок два") is True

    def test_arabic_indic(self):
        assert is_42("٤٢") is True

    def test_thai_digits(self):
        assert is_42("๔๒") is True

    def test_hindi(self):
        assert is_42("बयालीस") is True

    def test_not_42_words(self):
        assert is_42("forty-three") is False
        assert is_42("hello") is False


# ========== Roman Numerals ==========

class TestRoman:
    def test_standard(self):
        assert is_42("XLII") is True

    def test_lowercase(self):
        assert is_42("xlii") is True

    def test_mixed_case(self):
        assert is_42("Xlii") is True
        assert is_42("xLiI") is True

    def test_not_42_roman(self):
        assert is_42("XLIII") is False  # 43
        assert is_42("XLI") is False    # 41
        assert is_42("L") is False      # 50


# ========== Math Expressions ==========

class TestMathExpr:
    def test_simple_multiply(self):
        assert is_42("6 * 7") is True

    def test_simple_add(self):
        assert is_42("40 + 2") is True

    def test_complex_expression(self):
        assert is_42("(122*381+6)**0 + 41") is True

    def test_power_with_caret(self):
        assert is_42("2^5 + 10") is True

    def test_division(self):
        assert is_42("84 / 2") is True

    def test_floor_division(self):
        assert is_42("85 // 2") is True

    def test_modulo(self):
        assert is_42("142 % 100") is True

    def test_not_42_expr(self):
        assert is_42("6 * 8") is False
        assert is_42("1 + 1") is False

    def test_nested_parens(self):
        assert is_42("((21) * 2)") is True


# ========== Base Conversions ==========

class TestBaseConvert:
    def test_binary_prefix(self):
        assert is_42("0b101010") is True

    def test_octal_prefix(self):
        assert is_42("0o52") is True

    def test_hex_prefix(self):
        assert is_42("0x2A") is True
        assert is_42("0x2a") is True

    def test_binary_suffix(self):
        assert is_42("101010b") is True

    def test_hex_suffix(self):
        assert is_42("2Ah") is True

    def test_scientific(self):
        assert is_42("4.2e1") is True
        assert is_42("4.2E1") is True

    def test_fullwidth(self):
        assert is_42("４２") is True

    def test_circled_digits(self):
        assert is_42("④②") is True

    def test_persian_digits(self):
        assert is_42("۴۲") is True

    def test_not_42_base(self):
        assert is_42("0b111") is False     # 7
        assert is_42("0xFF") is False      # 255
        assert is_42("４３") is False       # full-width 43


# ========== Cultural References ==========

class TestCultural:
    def test_the_answer(self):
        assert is_42("The Answer to Life, the Universe, and Everything") is True

    def test_deep_thought(self):
        assert is_42("Deep Thought") is True

    def test_dont_panic(self):
        assert is_42("Don't Panic") is True
        assert is_42("dont panic") is True

    def test_hitchhikers_guide(self):
        assert is_42("Hitchhiker's Guide to the Galaxy") is True

    def test_six_times_nine(self):
        assert is_42("six times nine") is True

    def test_chinese_cultural(self):
        assert is_42("生命、宇宙以及一切的答案") is True
        assert is_42("宇宙的答案") is True
        assert is_42("银河系漫游指南") is True

    def test_the_answer_simple(self):
        assert is_42("the answer") is True

    def test_ultimate_answer(self):
        assert is_42("the ultimate answer") is True

    def test_not_cultural(self):
        assert is_42("random phrase") is False


# ========== Creative ==========

class TestCreative:
    def test_42_exclamation_marks(self):
        assert is_42("!" * 42) is True

    def test_42_stars(self):
        assert is_42("*" * 42) is True

    def test_42_hash(self):
        assert is_42("#" * 42) is True

    def test_not_42_chars(self):
        assert is_42("!" * 41) is False
        assert is_42("!" * 43) is False

    def test_mixed_chars_not_42(self):
        assert is_42("!" * 21 + "?" * 21) is False  # 42 chars but not identical

    def test_morse_code(self):
        assert is_42("....- ..---") is True

    def test_morse_code_no_space(self):
        assert is_42("....−..−−−") is True  # with unicode dashes


# ========== why_42 ==========

class TestWhy42:
    def test_returns_string_for_42(self):
        result = why_42(42)
        assert isinstance(result, str)
        assert "42" in result

    def test_returns_none_for_not_42(self):
        assert why_42(43) is None

    def test_roman_explanation(self):
        result = why_42("XLII")
        assert result is not None
        assert "Roman" in result

    def test_math_explanation(self):
        result = why_42("6 * 7")
        assert result is not None
        assert "math" in result

    def test_cultural_explanation(self):
        result = why_42("Deep Thought")
        assert result is not None
        assert "Douglas Adams" in result
