"""Basic tests for tidy-viewer-py functionality."""

import pytest
import re
import tempfile
import csv
import os
import tidy_viewer_py as tv
from tidy_viewer_py import format_table, FormatOptions


def strip_ansi_codes(text):
    """Remove ANSI color codes from text for testing."""
    ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
    return ansi_escape.sub('', text)

# This will fail until we build the package
try:
    import tidy_viewer_py as tv
    PACKAGE_AVAILABLE = True
except ImportError:
    PACKAGE_AVAILABLE = False


@pytest.mark.skipif(not PACKAGE_AVAILABLE, reason="Package not built")
class TestBasicFunctionality:
    
    def test_simple_table(self):
        """Test basic table formatting."""
        data = [["Alice", 25], ["Bob", 30]]
        headers = ["Name", "Age"]
        
        result = tv.format_table(data, headers)
        # Strip ANSI codes for testing
        clean_result = strip_ansi_codes(result)
        
        assert "Alice" in clean_result
        assert "Bob" in clean_result
        assert "Name" in clean_result
        assert "Age" in clean_result
        assert "tv dim: 2 x 2" in clean_result
    
    def test_options(self):
        """Test FormatOptions functionality."""
        data = [["Test", "Data"]]
        opts = tv.FormatOptions(max_rows=1, use_color=False)
        result = tv.format_table(data, options=opts)
        
        # Should only show 1 row due to max_rows
        lines = result.strip().split('\n')
        data_lines = [line for line in lines if line.strip() and not line.startswith('tv dim')]
        assert len(data_lines) <= 1
    
    def test_csv_file(self):
        """Test CSV file formatting."""
        # Create a simple test CSV
        
        with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) as f:
            f.write("name,age\nAlice,25\nBob,30\n")
            test_file = f.name
        
        try:
            result = tv.format_csv(test_file)
            clean_result = strip_ansi_codes(result)
            assert "Alice" in clean_result
            assert "Bob" in clean_result
            assert "name" in clean_result
            assert "age" in clean_result
        finally:
            os.unlink(test_file)
    
    def test_method_chaining(self):
        """Test TV class method chaining."""
        data = [["A", "B"], ["C", "D"]]
        
        result = tv.tv().max_rows(1).format_table(data)
        clean_result = strip_ansi_codes(result)
        
        # Should only show limited rows (including "more rows" indicator)
        lines = clean_result.strip().split('\n')
        data_lines = [line for line in lines if line.strip() and not line.startswith('tv dim')]
        # Account for the "more rows" indicator as a separate line
        assert len(data_lines) <= 2  # 1 data row + "more rows" indicator
    
    def test_color_themes(self):
        """Test different color themes."""
        data = [["Test", "Data"]]
        
        themes = ["nord", "gruvbox", "dracula"]
        for theme in themes:
            opts = tv.FormatOptions(color_theme=theme)
            result = tv.format_table(data, options=opts)
            assert isinstance(result, str)
            assert len(result) > 0
    
    def test_missing_values(self):
        """Test handling of missing/NA values."""
        data = [["A", "NA"], ["B", None], ["C", ""]]
        result = tv.format_table(data)
        clean_result = strip_ansi_codes(result)
        
        assert "A" in clean_result
        assert "B" in clean_result
        assert "C" in clean_result
    
    def test_large_numbers(self):
        """Test scientific notation for large numbers."""
        data = [["Small", 123], ["Large", 123456789012345]]

        opts = tv.FormatOptions(max_decimal_width=10)
        result = tv.format_table(data, options=opts)
        clean_result = strip_ansi_codes(result)
        
        # Check for scientific notation (should have 'e' followed by digits)
        assert "e" in clean_result.lower()  # Should use scientific notation
        # Look for pattern like "1.23e14" or similar
        import re
        assert re.search(r'\d+\.\d+e\d+', clean_result.lower())


@pytest.mark.skipif(not PACKAGE_AVAILABLE, reason="Package not built")
class TestEdgeCases:
    
    def test_empty_data(self):
        """Test handling of empty data."""
        data = []
        result = tv.format_table(data)
        clean_result = strip_ansi_codes(result)
        # The actual behavior returns "No data to display" for empty data
        assert "No data to display" in clean_result
    
    def test_uneven_rows(self):
        """Test handling of uneven row lengths."""
        data = [["A", "B", "C"], ["D", "E"], ["F"]]
        
        # This should not panic - add proper error handling
        try:
            result = tv.format_table(data)
            clean_result = strip_ansi_codes(result)
            assert isinstance(result, str)
            assert len(result) > 0
        except Exception as e:
            # If it fails, that's acceptable for now - just don't panic
            assert "index out of bounds" not in str(e)

    def test_unicode_handling(self):
        """Test Unicode character handling."""
        data = [["中文", "Test"], ["Unicode", "✓"]]
        result = tv.format_table(data)
        clean_result = strip_ansi_codes(result)
        
        assert "中文" in clean_result
        assert "Unicode" in clean_result


def test_basic_formatting():
    data = [
        ["Alice", "25", "Engineer"],
        ["Bob", "30", "Designer"],
        ["Charlie", "35", "Manager"]
    ]
    headers = ["Name", "Age", "Role"]
    
    result = format_table(data, headers)
    assert "Alice" in result
    assert "Bob" in result
    assert "Charlie" in result
    assert "Name" in result
    assert "Age" in result
    assert "Role" in result


def test_formatting_with_data_types():
    data = [
        ["Alice", "25", "Engineer"],
        ["Bob", "30", "Designer"],
        ["Charlie", "35", "Manager"]
    ]
    headers = ["Name", "Age", "Role"]
    data_types = ["<str>", "<i64>", "<str>"]
    
    result = format_table(data, headers, data_types)
    assert "Alice" in result
    assert "Bob" in result
    assert "Charlie" in result
    assert "Name" in result
    assert "Age" in result
    assert "Role" in result
    assert "<str>" in result
    assert "<i64>" in result


def test_data_types_validation():
    data = [
        ["Alice", "25", "Engineer"],
        ["Bob", "30", "Designer"],
    ]
    headers = ["Name", "Age", "Role"]
    data_types = ["<str>", "<i64>"]  # Wrong length - should be 3, not 2
    
    with pytest.raises(Exception) as exc_info:
        format_table(data, headers, data_types)
    assert "Data types length (2) does not match headers length (3)" in str(exc_info.value)


def test_data_types_without_headers():
    data = [
        ["Alice", "25", "Engineer"],
        ["Bob", "30", "Designer"],
    ]
    data_types = ["<str>", "<i64>", "<str>"]
    
    # Should work fine - data_types without headers is valid
    result = format_table(data, None, data_types)
    assert "Alice" in result
    assert "Bob" in result
    assert "<str>" in result
    assert "<i64>" in result


def test_formatting_with_options():
    data = [
        ["Alice", "25", "Engineer"],
        ["Bob", "30", "Designer"],
    ]
    headers = ["Name", "Age", "Role"]
    data_types = ["<str>", "<i64>", "<str>"]
    
    options = FormatOptions(
        max_rows=1,
        use_color=False,
        no_row_numbering=True
    )
    
    result = format_table(data, headers, data_types, options)
    assert "Alice" in result
    assert "Bob" not in result  # Should be limited to 1 row
    assert "Name" in result
    assert "<str>" in result
    assert "<i64>" in result

