"""Tests for pyos/printers/Table.py — pure-logic helpers and display_state."""

import pytest

from pyos.printers.Table import _fit_text, _justify, _format_row, _compute_column_widths, Table


# ===========================================================================
# _fit_text
# ===========================================================================

class TestFitText:
    def test_width_zero(self):
        assert _fit_text("hello", 0) == ""

    def test_width_one(self):
        assert _fit_text("hello", 1) == "h"

    def test_width_two(self):
        assert _fit_text("hello", 2) == "he"

    def test_width_three_truncates_with_dots(self):
        assert _fit_text("hello", 3) == "..."

    def test_width_four_truncates_with_dots(self):
        assert _fit_text("hello world", 4) == "h..."

    def test_text_shorter_than_width(self):
        assert _fit_text("hi", 10) == "hi"

    def test_text_exact_width(self):
        assert _fit_text("abc", 3) == "abc"

    def test_empty_text(self):
        assert _fit_text("", 5) == ""


# ===========================================================================
# _justify
# ===========================================================================

class TestJustify:
    def test_left_align(self):
        result = _justify("hi", 6, "left")
        assert result == "hi    "
        assert len(result) == 6

    def test_right_align(self):
        result = _justify("hi", 6, "right")
        assert result == "    hi"
        assert len(result) == 6

    def test_center_align(self):
        result = _justify("hi", 6, "center")
        assert len(result) == 6
        assert "hi" in result
        # "  hi  "
        assert result == "  hi  "

    def test_text_longer_than_width_unchanged(self):
        result = _justify("toolong", 3, "left")
        assert result == "toolong"

    def test_unknown_align_defaults_to_left(self):
        result = _justify("hi", 6, "bogus")
        assert result == "hi    "


# ===========================================================================
# _format_row
# ===========================================================================

class TestFormatRow:
    def test_normal(self):
        result = _format_row(["a", "bb"], [3, 4], ["left", "left"], 1, " | ")
        # " a   " | " bb   "
        assert "a" in result
        assert "bb" in result

    def test_fewer_cells_than_columns(self):
        result = _format_row(["a"], [3, 4], ["left", "left"], 1, " | ")
        # Second cell should be empty string padded
        assert " | " in result

    def test_empty_delimiter(self):
        result = _format_row(["a", "b"], [2, 2], ["left", "left"], 0, "")
        assert "a" in result
        assert "b" in result

    def test_padding_zero(self):
        result = _format_row(["a"], [3], ["left"], 0, "|")
        assert result.startswith("a")


# ===========================================================================
# _compute_column_widths
# ===========================================================================

class TestComputeColumnWidths:
    def test_normal_fit(self):
        widths = _compute_column_widths(["Name", "Age"], [["Alice", "30"]], 80, 1, " | ", [0, 0])
        assert len(widths) == 2
        assert all(w > 0 for w in widths)

    def test_shrink_needed(self):
        widths = _compute_column_widths(
            ["A" * 50, "B" * 50],
            [],
            80,
            1,
            " | ",
            [0, 0],
        )
        assert sum(widths) <= 80

    def test_very_narrow_terminal(self):
        widths = _compute_column_widths(["Name", "Age"], [["Alice", "30"]], 10, 0, "", [0, 0])
        assert all(w >= 1 for w in widths)

    def test_single_column(self):
        widths = _compute_column_widths(["Title"], [["Hello"]], 80, 1, " | ", [0])
        assert len(widths) == 1
        assert widths[0] >= 5

    def test_empty_rows(self):
        widths = _compute_column_widths(["A", "B"], [], 80, 1, " | ", [0, 0])
        assert len(widths) == 2


# ===========================================================================
# Table.layout
# ===========================================================================

class TestTableLayout:
    def test_returns_dict_structure(self):
        layout = Table.layout(min_height=3, flex=2, max_height=20)
        assert layout["flex"] == 2
        assert layout["min_height"] == 3
        assert layout["max_height"] == 20

    def test_no_max_height(self):
        layout = Table.layout()
        assert "max_height" not in layout


# ===========================================================================
# Table.display_state
# ===========================================================================

class TestTableDisplayState:
    def test_returns_expected_keys(self):
        from pyos.testing import MockScreen

        screen = MockScreen(24, 80)
        state = Table.display_state(screen, ["Name", "Value"], [["a", "1"]])
        assert "headers" in state
        assert "rows" in state
        assert "items" in state
        assert "layout" in state
        assert "line_generator" in state
        assert callable(state["line_generator"])

    def test_handles_none_rows(self):
        from pyos.testing import MockScreen

        screen = MockScreen(24, 80)
        state = Table.display_state(screen, ["A"], None)
        assert state["rows"] == []
        assert state["items"] == []

    def test_handles_none_headers(self):
        from pyos.testing import MockScreen

        screen = MockScreen(24, 80)
        state = Table.display_state(screen, None, [["x"]])
        assert state["headers"] == []
