"""
Tests for boolean parsing in settings manager.

This module tests the parse_boolean() function which handles HTML checkbox
semantics and various boolean representations from forms, JSON, and environment
variables.

Note: parse_boolean is used internally for HTML form handling but is not
exported from the settings package. For API/config/database boolean conversion,
use to_bool from utilities.type_utils instead.
"""

import pytest

from local_deep_research.settings.manager import parse_boolean


class TestParseBooleanBasicTypes:
    """Test parse_boolean with basic Python types."""

    def test_boolean_true(self):
        """Test that True remains True."""
        assert parse_boolean(True) is True

    def test_boolean_false(self):
        """Test that False remains False."""
        assert parse_boolean(False) is False

    def test_none_is_false(self):
        """Test that None converts to False."""
        assert parse_boolean(None) is False


class TestParseBooleanStringValues:
    """Test parse_boolean with string representations."""

    @pytest.mark.parametrize(
        "value",
        [
            "true",
            "True",
            "TRUE",
            "yes",
            "Yes",
            "YES",
            "on",
            "On",
            "ON",
            "1",
            "enabled",
            "ENABLED",
            "checked",
            "CHECKED",
            "any_random_string",
            "  true  ",  # With whitespace
            "  yes  ",
            "  on  ",
        ],
    )
    def test_truthy_strings(self, value):
        """Test that various truthy string values convert to True."""
        assert parse_boolean(value) is True

    @pytest.mark.parametrize(
        "value",
        [
            "false",
            "False",
            "FALSE",
            "no",
            "No",
            "NO",
            "off",
            "Off",
            "OFF",
            "0",
            "",
            "  ",  # Whitespace only
            "  false  ",  # With whitespace
            "  no  ",
            "  off  ",
            "  0  ",
        ],
    )
    def test_falsy_strings(self, value):
        """Test that various falsy string values convert to False."""
        assert parse_boolean(value) is False


class TestParseBooleanHTMLFormValues:
    """Test parse_boolean with HTML form submission values."""

    def test_checkbox_checked_standard(self):
        """Test standard HTML checkbox checked value."""
        # Most browsers send "on" for checked checkboxes
        # "on" is NOT in FALSY_VALUES, so it's treated as True
        assert parse_boolean("on") is True

    def test_checkbox_unchecked(self):
        """Test HTML checkbox unchecked (empty string from hidden input)."""
        assert parse_boolean("") is False

    def test_checkbox_with_custom_value(self):
        """Test HTML checkbox with custom value attribute."""
        # <input type="checkbox" value="custom">
        assert parse_boolean("custom") is True

    def test_hidden_fallback_false(self):
        """Test hidden input fallback value for unchecked checkbox."""
        # Common pattern: <input type="hidden" value="false">
        assert parse_boolean("false") is False


class TestParseBooleanJSONValues:
    """Test parse_boolean with values from JSON parsing."""

    def test_json_true(self):
        """Test JSON boolean true."""
        assert parse_boolean(True) is True

    def test_json_false(self):
        """Test JSON boolean false."""
        assert parse_boolean(False) is False

    def test_json_string_true(self):
        """Test JSON string "true"."""
        assert parse_boolean("true") is True

    def test_json_string_false(self):
        """Test JSON string "false"."""
        assert parse_boolean("false") is False


class TestParseBooleanEnvironmentVariables:
    """Test parse_boolean with environment variable values."""

    @pytest.mark.parametrize(
        "env_value",
        ["1", "true", "True", "TRUE", "yes", "YES", "on", "ON", "enabled"],
    )
    def test_common_env_true_values(self, env_value):
        """Test common environment variable values for true."""
        assert parse_boolean(env_value) is True

    @pytest.mark.parametrize(
        "env_value",
        ["0", "false", "False", "FALSE", "no", "NO", "off", "OFF", ""],
    )
    def test_common_env_false_values(self, env_value):
        """Test common environment variable values for false."""
        assert parse_boolean(env_value) is False


class TestParseBooleanEdgeCases:
    """Test parse_boolean with edge cases and unusual inputs."""

    def test_whitespace_only_is_false(self):
        """Test that whitespace-only strings are false."""
        assert parse_boolean("   ") is False
        assert parse_boolean("\t") is False
        assert parse_boolean("\n") is False

    def test_numeric_zero_is_false(self):
        """Test that numeric 0 converts to False."""
        assert parse_boolean(0) is False

    def test_numeric_nonzero_is_true(self):
        """Test that non-zero numbers convert to True."""
        assert parse_boolean(1) is True
        assert parse_boolean(42) is True
        assert parse_boolean(-1) is True
        assert parse_boolean(3.14) is True

    def test_empty_list_is_false(self):
        """Test that empty list converts to False."""
        assert parse_boolean([]) is False

    def test_nonempty_list_is_true(self):
        """Test that non-empty list converts to True."""
        assert parse_boolean([1, 2, 3]) is True
        assert parse_boolean(["false"]) is True  # Non-empty list

    def test_empty_dict_is_false(self):
        """Test that empty dict converts to False."""
        assert parse_boolean({}) is False

    def test_nonempty_dict_is_true(self):
        """Test that non-empty dict converts to True."""
        assert parse_boolean({"key": "value"}) is True

    def test_case_insensitive_handling(self):
        """Test that string comparison is case-insensitive."""
        assert parse_boolean("TrUe") is True
        assert parse_boolean("FaLsE") is False
        assert parse_boolean("YeS") is True
        assert parse_boolean("nO") is False

    def test_string_with_leading_trailing_spaces(self):
        """Test strings with leading/trailing whitespace are trimmed."""
        assert parse_boolean("  true  ") is True
        assert parse_boolean("  false  ") is False
        assert parse_boolean("  0  ") is False
        assert parse_boolean("  1  ") is True


class TestParseBooleanConsistency:
    """Test parse_boolean for consistency across different input sources."""

    def test_form_json_env_consistency_true(self):
        """Test that true values are consistent across input sources."""
        # Form data
        assert parse_boolean("true") is True
        # JSON
        assert parse_boolean(True) is True
        # Environment
        assert parse_boolean("1") is True

    def test_form_json_env_consistency_false(self):
        """Test that false values are consistent across input sources."""
        # Form data
        assert parse_boolean("false") is False
        assert parse_boolean("") is False
        # JSON
        assert parse_boolean(False) is False
        # Environment
        assert parse_boolean("0") is False

    def test_roundtrip_bool_to_string_to_bool(self):
        """Test roundtrip conversion: bool -> str -> bool."""
        # True roundtrip
        assert parse_boolean(str(True).lower()) is True
        # False roundtrip
        assert parse_boolean(str(False).lower()) is False


class TestParseBooleanHTMLSemantics:
    """
    Test parse_boolean for HTML checkbox semantics.

    HTML checkbox semantics: Any value present (except explicit false) = checked = True.
    This is documented behavior in the parse_boolean docstring.
    """

    def test_unchecked_checkbox_not_submitted(self):
        """Test unchecked checkbox (not in form data) = None = False."""
        assert parse_boolean(None) is False

    def test_unchecked_checkbox_hidden_fallback(self):
        """Test unchecked checkbox with hidden fallback value."""
        # Pattern: <input type="hidden" name="setting" value="false">
        #          <input type="checkbox" name="setting">
        # When unchecked, form submits hidden input value
        assert parse_boolean("false") is False

    def test_checked_checkbox_standard(self):
        """Test checked checkbox with standard value."""
        # Most browsers send "on" for checked checkboxes
        # "on" is NOT in FALSY_VALUES, so it's treated as True
        assert parse_boolean("on") is True

    def test_checked_checkbox_explicit_true(self):
        """Test checked checkbox with explicit "true" value."""
        # Pattern: <input type="checkbox" name="setting" value="true">
        assert parse_boolean("true") is True

    def test_checked_checkbox_value_one(self):
        """Test checked checkbox with value="1"."""
        # Pattern: <input type="checkbox" name="setting" value="1">
        assert parse_boolean("1") is True


class TestParseBooleanRegressions:
    """Test parse_boolean for known issues and regressions."""

    def test_issue_corrupted_value_detection(self):
        """
        Test that checkbox values are parsed before corrupted value detection.

        This prevents incorrect triggering of corrupted value detection when
        checkbox values come in as strings (e.g., "true") instead of booleans.

        Related to settings_routes.py:292-299
        """
        # String "true" from form should not be considered corrupted
        assert parse_boolean("true") is True
        assert isinstance(parse_boolean("true"), bool)

        # String "false" from form should not be considered corrupted
        assert parse_boolean("false") is False
        assert isinstance(parse_boolean("false"), bool)

    def test_ajax_vs_post_consistency(self):
        """
        Test consistency between AJAX (JSON) and traditional POST submissions.

        Related to settings_routes.py:1-38 dual-mode submission pattern.
        """
        # AJAX mode: JavaScript sends boolean
        ajax_checked = True
        ajax_unchecked = False

        # Traditional POST: Browser sends string
        post_checked = "true"
        post_unchecked = "false"

        # Both modes should produce same results
        assert parse_boolean(ajax_checked) == parse_boolean(post_checked)
        assert parse_boolean(ajax_unchecked) == parse_boolean(post_unchecked)
