"""Tests for the vendored tabulate module."""

from __future__ import annotations

from codeflash_python.ai._tabulate import (
    SEPARATING_LINE,
    _afterpoint,
    _is_multiline,
    _is_separating_line,
    _isbool,
    _isconvertible,
    _isint,
    _isnumber,
    _isnumber_with_thousands_separator,
    _padboth,
    _padleft,
    _padnone,
    _padright,
    _pipe_segment_with_colons,
    _strip_ansi,
    _type,
    _visible_width,
    tabulate,
    tabulate_formats,
)


class TestTabulate:
    """Tests for the main tabulate function."""

    def test_simple_table(self) -> None:
        """Simple format produces a readable table."""
        data = [["Alice", 24], ["Bob", 30]]
        result = tabulate(data, headers=["Name", "Age"], tablefmt="simple")

        assert "Name" in result
        assert "Age" in result
        assert "Alice" in result
        assert "Bob" in result

    def test_pipe_format(self) -> None:
        """Pipe format produces markdown-style table."""
        data = [["Alice", 24], ["Bob", 30]]
        result = tabulate(data, headers=["Name", "Age"], tablefmt="pipe")

        assert result.startswith("|")
        assert "Alice" in result
        assert "|" in result

    def test_empty_table(self) -> None:
        """Empty data returns empty string."""
        assert "" == tabulate([], headers=[])

    def test_none_data(self) -> None:
        """None data is treated as empty."""
        assert "" == tabulate(None)

    def test_headers_only(self) -> None:
        """Table with headers but no data rows."""
        result = tabulate([], headers=["A", "B"], tablefmt="simple")

        assert "A" in result
        assert "B" in result

    def test_numeric_alignment(self) -> None:
        """Numbers are right-aligned by default in simple format."""
        data = [["x", 1], ["y", 200]]
        result = tabulate(data, headers=["Name", "Val"], tablefmt="simple")

        assert "1" in result
        assert "200" in result

    def test_missing_values(self) -> None:
        """None values use the missingval placeholder."""
        data = [["Alice", None]]
        result = tabulate(
            data,
            headers=["Name", "Age"],
            missingval="N/A",
            tablefmt="simple",
        )

        assert "N/A" in result

    def test_dict_data(self) -> None:
        """Dict input with headers='keys' uses dict keys as headers."""
        data = {"Name": ["Alice", "Bob"], "Age": [24, 30]}
        result = tabulate(data, headers="keys", tablefmt="simple")

        assert "Name" in result
        assert "Alice" in result

    def test_disable_numparse(self) -> None:
        """disable_numparse treats numbers as strings."""
        data = [["001", "002"]]
        result = tabulate(
            data,
            headers=["A", "B"],
            disable_numparse=True,
            tablefmt="simple",
        )

        assert "001" in result

    def test_float_format(self) -> None:
        """Custom float format is applied."""
        data = [[3.14159]]
        result = tabulate(
            data,
            headers=["Pi"],
            floatfmt=".2f",
            tablefmt="simple",
        )

        assert "3.14" in result

    def test_preserve_whitespace(self) -> None:
        """preserve_whitespace prevents stripping."""
        data = [["  padded  "]]
        result = tabulate(
            data,
            headers=["Val"],
            preserve_whitespace=True,
            tablefmt="pipe",
        )

        assert "  padded  " in result

    def test_separating_line_in_rows(self) -> None:
        """SEPARATING_LINE constant inserts a separator row."""
        data = [["a", 1], [SEPARATING_LINE], ["b", 2]]
        result = tabulate(data, headers=["X", "Y"], tablefmt="simple")

        assert "a" in result
        assert "b" in result

    def test_colglobalalign(self) -> None:
        """Global column alignment is applied."""
        data = [["Alice", 24], ["Bob", 30]]
        result = tabulate(
            data,
            headers=["Name", "Age"],
            colglobalalign="center",
            tablefmt="pipe",
        )

        assert "|" in result

    def test_firstrow_headers(self) -> None:
        """headers='firstrow' uses the first row as headers."""
        data = [["Name", "Age"], ["Alice", 24]]
        result = tabulate(data, headers="firstrow", tablefmt="simple")

        assert "Name" in result
        assert "Alice" in result


class TestTabulateFormats:
    """Tests for tabulate_formats constant."""

    def test_contains_pipe(self) -> None:
        """pipe format is available."""
        assert "pipe" in tabulate_formats

    def test_contains_simple(self) -> None:
        """simple format is available."""
        assert "simple" in tabulate_formats

    def test_is_sorted(self) -> None:
        """Format list is sorted."""
        assert tabulate_formats == sorted(tabulate_formats)


class TestTypeDetection:
    """Tests for type detection helpers."""

    def test_isnumber_int(self) -> None:
        """Integers are numbers."""
        assert _isnumber(42) is True

    def test_isnumber_float(self) -> None:
        """Floats are numbers."""
        assert _isnumber(3.14) is True

    def test_isnumber_string_int(self) -> None:
        """String integers are numbers."""
        assert _isnumber("42") is True

    def test_isnumber_string_float(self) -> None:
        """String floats are numbers."""
        assert _isnumber("3.14") is True

    def test_isnumber_nan(self) -> None:
        """'NaN' string is a number."""
        assert _isnumber("NaN") is True

    def test_isnumber_inf(self) -> None:
        """'inf' string is a number."""
        assert _isnumber("inf") is True

    def test_isnumber_not_a_number(self) -> None:
        """Non-numeric string is not a number."""
        assert _isnumber("hello") is False

    def test_isint_true(self) -> None:
        """Actual int returns True."""
        assert _isint(42) is True

    def test_isint_string(self) -> None:
        """String integer returns True."""
        assert _isint("42") is True

    def test_isint_float(self) -> None:
        """Float is not an int."""
        assert _isint(3.14) is False

    def test_isbool_true(self) -> None:
        """Python bool returns True."""
        assert _isbool(True) is True
        assert _isbool(False) is True

    def test_isbool_string(self) -> None:
        """String booleans are detected."""
        assert _isbool("True") is True
        assert _isbool("False") is True

    def test_isbool_other(self) -> None:
        """Non-boolean returns False."""
        assert _isbool("yes") is False
        assert _isbool(1) is False

    def test_isconvertible_int(self) -> None:
        """'42' is convertible to int."""
        assert _isconvertible(int, "42") is True

    def test_isconvertible_fails(self) -> None:
        """'abc' is not convertible to int."""
        assert _isconvertible(int, "abc") is False

    def test_isnumber_with_thousands_separator(self) -> None:
        """Thousands-separated numbers are detected."""
        assert _isnumber_with_thousands_separator("1,000") is True
        assert _isnumber_with_thousands_separator("1,000.50") is True

    def test_isnumber_with_thousands_separator_invalid(self) -> None:
        """Non-numeric strings are rejected."""
        assert _isnumber_with_thousands_separator("abc") is False

    def test_type_none(self) -> None:
        """None returns NoneType."""
        assert _type(None) is type(None)

    def test_type_empty_string(self) -> None:
        """Empty string returns NoneType."""
        assert _type("") is type(None)

    def test_type_bool(self) -> None:
        """Bool values return bool type."""
        assert _type(True) is bool

    def test_type_int(self) -> None:
        """Int string returns int type."""
        assert _type("42") is int

    def test_type_float(self) -> None:
        """Float string returns float type."""
        assert _type("3.14") is float

    def test_type_string(self) -> None:
        """Non-numeric string returns str type."""
        assert _type("hello") is str


class TestAfterpoint:
    """Tests for _afterpoint decimal position detection."""

    def test_integer(self) -> None:
        """Integers have -1 afterpoint."""
        assert -1 == _afterpoint(42)

    def test_float_string(self) -> None:
        """Decimal digits are counted."""
        assert 2 == _afterpoint("3.14")

    def test_no_decimal(self) -> None:
        """String integer has -1 afterpoint."""
        assert -1 == _afterpoint("42")

    def test_non_number(self) -> None:
        """Non-numbers return -1."""
        assert -1 == _afterpoint("abc")


class TestPadding:
    """Tests for padding functions."""

    def test_padleft(self) -> None:
        """Left padding right-aligns the string."""
        assert "   hi" == _padleft(5, "hi")

    def test_padright(self) -> None:
        """Right padding left-aligns the string."""
        assert "hi   " == _padright(5, "hi")

    def test_padboth(self) -> None:
        """Both padding centers the string."""
        result = _padboth(6, "hi")
        assert "hi" in result
        assert 6 == len(result)

    def test_padnone(self) -> None:
        """No padding returns the string unchanged."""
        assert "hi" == _padnone(999, "hi")


class TestAnsiHandling:
    """Tests for ANSI escape code handling."""

    def test_strip_ansi_plain(self) -> None:
        """Plain string passes through unchanged."""
        assert "hello" == _strip_ansi("hello")

    def test_strip_ansi_colored(self) -> None:
        """ANSI color codes are removed."""
        colored = "\033[31mred\033[0m"
        assert "red" == _strip_ansi(colored)

    def test_visible_width_plain(self) -> None:
        """Plain string width is its length."""
        assert 5 == _visible_width("hello")

    def test_visible_width_ansi(self) -> None:
        """ANSI codes don't count toward visible width."""
        colored = "\033[31mred\033[0m"
        assert 3 == _visible_width(colored)


class TestMultiline:
    """Tests for multiline detection."""

    def test_newline_detected(self) -> None:
        """String with newline is multiline."""
        assert _is_multiline("a\nb") is True

    def test_carriage_return_detected(self) -> None:
        """String with carriage return is multiline."""
        assert _is_multiline("a\rb") is True

    def test_single_line(self) -> None:
        """String without line breaks is not multiline."""
        assert _is_multiline("hello") is False


class TestSeparatingLine:
    """Tests for separating line detection."""

    def test_separating_line_list(self) -> None:
        """List starting with SEPARATING_LINE is detected."""
        assert _is_separating_line([SEPARATING_LINE]) is True

    def test_normal_row(self) -> None:
        """Normal data row is not a separating line."""
        assert _is_separating_line(["hello", "world"]) is False

    def test_empty_list(self) -> None:
        """Empty list is not a separating line."""
        assert _is_separating_line([]) is False


class TestPipeSegment:
    """Tests for pipe format alignment segments."""

    def test_right_alignment(self) -> None:
        """Right alignment ends with colon."""
        result = _pipe_segment_with_colons("right", 5)
        assert result.endswith(":")
        assert 5 == len(result)

    def test_left_alignment(self) -> None:
        """Left alignment starts with colon."""
        result = _pipe_segment_with_colons("left", 5)
        assert result.startswith(":")
        assert 5 == len(result)

    def test_center_alignment(self) -> None:
        """Center alignment has colons on both ends."""
        result = _pipe_segment_with_colons("center", 5)
        assert result.startswith(":")
        assert result.endswith(":")
        assert 5 == len(result)

    def test_default_alignment(self) -> None:
        """Default alignment is all dashes."""
        result = _pipe_segment_with_colons("", 5)
        assert "-----" == result


class TestIntegrationWithCreatePr:
    """Tests verifying tabulate works as used by _create_pr."""

    def test_pipe_format_with_performance_data(self) -> None:
        """Pipe format table matches the PR description use case."""
        headers = [
            "Test File::Test Function",
            "Original",
            "Optimized",
            "Speedup",
        ]
        rows = [
            ["`test_a.py::test_func`", "100ms", "50ms", "50%"],
            ["`test_b.py::test_other`", "200ms", "80ms", "60%"],
        ]

        result = tabulate(
            headers=headers,
            tabular_data=rows,
            tablefmt="pipe",
            colglobalalign=None,
            preserve_whitespace=True,
        )

        assert "|" in result
        assert "test_a.py" in result
        assert "50%" in result
        lines = result.strip().split("\n")
        assert len(lines) >= 3

    def test_empty_rows_returns_empty(self) -> None:
        """Empty rows with headers still produces a header-only table."""
        headers = ["A", "B", "C", "D"]
        result = tabulate(
            headers=headers,
            tabular_data=[],
            tablefmt="pipe",
            colglobalalign=None,
            preserve_whitespace=True,
        )

        assert "A" in result
