"""
全面的边界条件和异常场景测试
"""

import pytest

from src.symphra_excel import (
    CellStyle,
    ValidationError,
    Workbook,
)


class TestNullAndEmptyValues:
    """空值和None测试"""

    def test_empty_string_in_cell(self):
        """测试单元格中的空字符串"""
        wb = Workbook()
        sheet = wb.active
        sheet.set_cell_value("A1", "")
        assert sheet.get_cell_value("A1") == ""

    def test_none_value_in_cell(self):
        """测试单元格中的None值"""
        wb = Workbook()
        sheet = wb.active
        sheet.set_cell_value("A1", None)
        assert sheet.get_cell_value("A1") is None

    def test_empty_list_in_range(self):
        """测试范围中的空列表"""
        wb = Workbook()
        sheet = wb.active
        sheet.set_range_values("A1", [])
        # 应该不抛出异常

    def test_list_with_none_elements(self):
        """测试包含None元素的列表"""
        wb = Workbook()
        sheet = wb.active
        sheet.set_range_values("A1", [[1, None, 3], [None, 5, None]])

        assert sheet.get_cell_value("A1") == 1
        assert sheet.get_cell_value("B1") is None
        assert sheet.get_cell_value("C1") == 3
        assert sheet.get_cell_value("B2") == 5


class TestExtremeValues:
    """极值测试"""

    def test_max_integer_value(self):
        """测试最大整数值"""
        wb = Workbook()
        sheet = wb.active
        max_int = 2**31 - 1  # Excel安全整数范围
        sheet.set_cell_value("A1", max_int)
        assert sheet.get_cell_value("A1") == max_int

    def test_min_integer_value(self):
        """测试最小整数值"""
        wb = Workbook()
        sheet = wb.active
        min_int = -(2**31)
        sheet.set_cell_value("A1", min_int)
        assert sheet.get_cell_value("A1") == min_int

    def test_very_long_string(self):
        """测试超长字符串"""
        wb = Workbook()
        sheet = wb.active
        long_string = "A" * 10000  # 超长字符串
        sheet.set_cell_value("A1", long_string)
        assert sheet.get_cell_value("A1") == long_string

    def test_unicode_and_emojis(self):
        """测试Unicode和表情符号"""
        wb = Workbook()
        sheet = wb.active
        text = "测试中文 🎉 emoji 😀 and special chars: ♥️"
        sheet.set_cell_value("A1", text)
        assert sheet.get_cell_value("A1") == text

    def test_special_characters(self):
        """测试特殊字符"""
        wb = Workbook()
        sheet = wb.active

        # 换行符
        sheet.set_cell_value("A1", "Line1\nLine2")
        assert "\n" in str(sheet.get_cell_value("A1"))

        # 制表符
        sheet.set_cell_value("A2", "Col1\tCol2")
        assert "\t" in str(sheet.get_cell_value("A2"))

        # 混合特殊字符
        mixed = "Tab:\t Newline:\n Return:\r Quote:\" Apostrophe:'"
        sheet.set_cell_value("A3", mixed)

    def test_large_number_of_rows(self):
        """测试大量行数据"""
        wb = Workbook()
        sheet = wb.active

        # 写入1000行
        for i in range(1000):
            sheet.set_cell_value(f"A{i + 1}", i)

        # 验证
        assert sheet.get_cell_value("A1") == 0
        assert sheet.get_cell_value("A500") == 499
        assert sheet.get_cell_value("A1000") == 999


class TestInvalidInputs:
    """无效输入测试"""

    def test_invalid_cell_reference(self):
        """测试无效单元格引用"""
        wb = Workbook()
        sheet = wb.active

        with pytest.raises((ValidationError, Exception)):
            sheet.set_cell_value("INVALID123", "value")

    def test_negative_row_column(self):
        """测试负数行列索引"""
        Workbook()

        # insert_rows/delete_rows使用负数索引应该抛出异常或被openpyxl处理
        # 这里测试不会崩溃

    def test_wrong_type_arguments(self):
        """测试错误类型的参数"""
        wb = Workbook()
        sheet = wb.active

        # 设置单元格值接受基本类型
        sheet.set_cell_value("A1", 123)

        # 复杂类型会被openpyxl拒绝,应该抛出ValidationError
        with pytest.raises((ValidationError, ValueError)):
            sheet.set_cell_value("A2", [1, 2, 3])  # 列表

        with pytest.raises((ValidationError, ValueError)):
            sheet.set_cell_value("A3", {"key": "value"})  # 字典


class TestDataTypes:
    """数据类型测试"""

    def test_integer_values(self):
        """测试整数值"""
        wb = Workbook()
        sheet = wb.active

        sheet.set_cell_value("A1", 0)
        sheet.set_cell_value("A2", 123)
        sheet.set_cell_value("A3", -456)

        assert sheet.get_cell_value("A1") == 0
        assert sheet.get_cell_value("A2") == 123
        assert sheet.get_cell_value("A3") == -456

    def test_float_values(self):
        """测试浮点数值"""
        wb = Workbook()
        sheet = wb.active

        sheet.set_cell_value("A1", 3.14)
        sheet.set_cell_value("A2", -2.71828)
        sheet.set_cell_value("A3", 0.0)

        assert abs(sheet.get_cell_value("A1") - 3.14) < 1e-10
        assert abs(sheet.get_cell_value("A2") - (-2.71828)) < 1e-10
        assert sheet.get_cell_value("A3") == 0.0

    def test_boolean_values(self):
        """测试布尔值"""
        wb = Workbook()
        sheet = wb.active

        sheet.set_cell_value("A1", True)
        sheet.set_cell_value("A2", False)

        assert sheet.get_cell_value("A1") is True
        assert sheet.get_cell_value("A2") is False

    def test_string_values(self):
        """测试字符串值"""
        wb = Workbook()
        sheet = wb.active

        sheet.set_cell_value("A1", "Hello")
        sheet.set_cell_value("A2", "")
        sheet.set_cell_value("A3", "123")

        assert sheet.get_cell_value("A1") == "Hello"
        assert sheet.get_cell_value("A2") == ""
        assert sheet.get_cell_value("A3") == "123"

    def test_formula_values(self):
        """测试公式值"""
        wb = Workbook()
        sheet = wb.active

        sheet.set_cell_value("A1", 10)
        sheet.set_cell_value("A2", 20)
        sheet.set_cell_value("A3", "=A1+A2")

        # 公式会被存储但不会自动计算
        assert sheet.get_cell_value("A3") == "=A1+A2"


class TestStyleEdgeCases:
    """样式边界条件测试"""

    def test_apply_none_style(self):
        """测试应用None样式"""
        wb = Workbook()
        sheet = wb.active

        sheet.set_cell_value("A1", "Test", style=None)
        # 应该不抛出异常

    def test_apply_empty_style(self):
        """测试应用空样式"""
        wb = Workbook()
        sheet = wb.active

        empty_style = CellStyle()
        sheet.set_cell_value("A1", "Test", style=empty_style)
        # 应该不抛出异常

    def test_multiple_styles_same_cell(self):
        """测试同一单元格多次应用样式"""
        wb = Workbook()
        sheet = wb.active

        sheet.set_cell_value("A1", "Test")

        # 应用多次不同样式
        for i in range(10):
            style = CellStyle()
            sheet.apply_style("A1", style)

        # 应该不抛出异常


class TestWorkbookEdgeCases:
    """工作簿边界条件测试"""

    def test_create_many_worksheets(self):
        """测试创建大量工作表"""
        wb = Workbook()

        # 创建100个工作表
        for i in range(100):
            wb.create_worksheet(f"Sheet{i}")

        assert len(wb.get_sheet_names()) == 101  # +1 默认的active sheet

    def test_worksheet_name_with_special_characters(self):
        """测试包含特殊字符的工作表名"""
        wb = Workbook()

        # 测试各种特殊字符
        names = [
            "Sheet_1",
            "Sheet-2",
            "测试工作表",
            "Sheet 3",  # 空格
        ]

        for name in names:
            try:
                wb.create_worksheet(name)
            except Exception:
                # 某些特殊字符可能不被允许
                pass

    def test_duplicate_worksheet_names(self):
        """测试重复的工作表名"""
        wb = Workbook()

        wb.create_worksheet("Test")

        # 尝试创建同名工作表
        # openpyxl会自动重命名或抛出异常
        try:
            wb.create_worksheet("Test")
        except Exception:
            pass


class TestMemoryAndPerformance:
    """内存和性能相关测试"""

    def test_large_data_set(self):
        """测试大数据集"""
        wb = Workbook()
        sheet = wb.active

        # 写入10000个单元格
        for i in range(100):
            for j in range(100):
                col_idx = j % 26
                sheet.set_cell_value(f"{chr(65 + col_idx)}{i + 1}", f"Data{i},{j}")

        # 验证部分数据 - 最后写入的值会覆盖
        assert sheet.get_cell_value("A1").startswith("Data0,")
        assert sheet.get_cell_value("A100").startswith("Data99,")

    def test_repeated_operations(self):
        """测试重复操作"""
        wb = Workbook()
        sheet = wb.active

        # 重复写入同一单元格1000次
        for i in range(1000):
            sheet.set_cell_value("A1", i)

        assert sheet.get_cell_value("A1") == 999


class TestConcurrency:
    """并发场景测试(使用pytest-asyncio)"""

    @pytest.mark.asyncio
    async def test_async_workbook_creation(self):
        """测试异步工作簿创建"""
        try:
            from src.symphra_excel import AsyncWorkbook

            wb = AsyncWorkbook()
            await wb.create()

            sheet = await wb.create_worksheet("TestSheet")
            await sheet.set_cell_value("A1", "Async Test")

            value = await sheet.get_cell_value("A1")
            assert value == "Async Test"
        except ImportError:
            pytest.skip("AsyncWorkbook not available")


class TestErrorRecovery:
    """错误恢复测试"""

    def test_continue_after_validation_error(self):
        """测试验证错误后继续操作"""
        wb = Workbook()
        sheet = wb.active

        # 触发错误
        try:
            sheet.set_cell_value("INVALID", "test")
        except (ValidationError, Exception):
            pass

        # 继续正常操作
        sheet.set_cell_value("A1", "normal")
        assert sheet.get_cell_value("A1") == "normal"

    def test_recover_from_write_only_error(self):
        """测试从只写模式错误恢复"""
        wb = Workbook(write_only=True)
        sheet = wb.active

        # 尝试读取(会失败)
        try:
            sheet.get_cell_value("A1")
        except ValidationError:
            pass

        # append操作应该正常
        sheet.append_row([1, 2, 3])


class TestComplexScenarios:
    """复杂场景测试"""

    def test_mixed_data_types_in_range(self):
        """测试范围中包含混合数据类型"""
        wb = Workbook()
        sheet = wb.active

        data = [
            ["Name", "Age", "Score", "Pass"],
            ["Alice", 25, 95.5, True],
            ["Bob", 30, 87.3, True],
            ["Charlie", None, 62.0, False],
            [None, 28, None, True],
        ]

        sheet.set_range_values("A1", data)

        # 验证
        assert sheet.get_cell_value("A1") == "Name"
        assert sheet.get_cell_value("B2") == 25
        assert abs(sheet.get_cell_value("C3") - 87.3) < 1e-10
        assert sheet.get_cell_value("D4") is False
        assert sheet.get_cell_value("A5") is None

    def test_interleaved_operations(self):
        """测试交错操作"""
        wb = Workbook()
        sheet1 = wb.create_worksheet("Sheet1")
        sheet2 = wb.create_worksheet("Sheet2")

        # 交错写入
        sheet1.set_cell_value("A1", "Sheet1 Data")
        sheet2.set_cell_value("A1", "Sheet2 Data")
        sheet1.set_cell_value("A2", "More Data")
        sheet2.set_cell_value("A2", "More Data 2")

        # 验证
        assert sheet1.get_cell_value("A1") == "Sheet1 Data"
        assert sheet2.get_cell_value("A1") == "Sheet2 Data"
