"""同步核心能力回归测试。"""

from pathlib import Path
from typing import Iterator

import pytest
from PIL import Image

from src.symphra_excel import TemplateWorkbook, Workbook
from src.symphra_excel.memory_ops import InMemoryWorkbook, MemoryOptimizedWorkbook
from src.symphra_excel.utils.exceptions import ValidationError
from src.symphra_excel.utils.large_data_processor import DataFormat, LargeDataProcessor
from src.symphra_excel.utils.memory_manager import MemoryStrategy


def _data_generator() -> Iterator[list[list[int]]]:
    yield [[1, 2], [3, 4]]
    yield [[5, 6]]


def test_large_data_processor_export_excel(tmp_path: Path) -> None:
    """验证 Excel 流式导出结果与统计信息。"""
    processor = LargeDataProcessor()
    output_path = tmp_path / "export.xlsx"
    data_iter = _data_generator()

    stats = processor.export_large_dataset(
        data_iter,
        output_path,
        format_type=DataFormat.EXCEL,
        headers=["col_a", "col_b"],
    )

    assert stats.rows_processed == 4
    assert not stats.errors
    assert output_path.exists()

    workbook = Workbook.load(output_path)
    sheet = workbook.active
    assert sheet.get_range_values("A1:B4")[:2] == [
        ["col_a", "col_b"],
        [1, 2],
    ]


def test_in_memory_workbook_merge_append() -> None:
    """合并内存工作簿时应复制工作表数据。"""
    primary = InMemoryWorkbook()
    primary_sheet = primary.create_worksheet("Data")
    primary_sheet.set_range_values("A1", [["base", 1]])

    secondary = InMemoryWorkbook()
    secondary_sheet = secondary.create_worksheet("Data")
    secondary_sheet.set_range_values("A1", [["extra", 2]])

    merged = primary.merge_with(secondary, merge_strategy="append")
    assert "Data" in merged.get_sheet_names()
    assert any(name.startswith("Data_") for name in merged.get_sheet_names())

    appended_name = next(
        name for name in merged.get_sheet_names() if name.startswith("Data_")
    )
    appended_sheet = merged.get_worksheet(appended_name)
    assert appended_sheet is not None
    assert appended_sheet.get_cell_value("A1") == "extra"
    assert appended_sheet.get_cell_value("B1") == 2


def test_template_workbook_render_cell() -> None:
    """模板渲染应正确替换占位符。"""
    template_wb = TemplateWorkbook()
    sheet = template_wb.active
    sheet.set_value("A1", "{{ user.name }}")

    template_wb.render({"user": {"name": "Alice"}})

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


def test_workbook_write_only_append(tmp_path: Path) -> None:
    """write_only 模式需要通过 append 写入数据。"""
    workbook = Workbook(mode="write_only")
    sheet = workbook.create_worksheet("Stream")
    sheet.append_row(["col_a", "col_b"])
    sheet.append_rows([[1, 2], [3, 4]])

    output = tmp_path / "write_only.xlsx"
    workbook.save(output)

    loaded = Workbook.load(output)
    loaded_sheet = loaded.get_worksheet("Stream")
    assert loaded_sheet is not None
    assert loaded_sheet.get_range_values("A1:B3") == [
        ["col_a", "col_b"],
        [1, 2],
        [3, 4],
    ]


def test_workbook_read_only_mode(tmp_path: Path) -> None:
    """read_only 模式只能读取，写入应报错。"""
    source = tmp_path / "source.xlsx"
    workbook = Workbook()
    sheet = workbook.active
    sheet.set_cell_value("A1", "origin")
    workbook.save(source)

    readonly = Workbook(source, mode="read_only")
    ro_sheet = readonly.get_worksheet("Sheet")
    assert ro_sheet is not None
    assert ro_sheet.get_cell_value("A1") == "origin"

    with pytest.raises(ValidationError):
        ro_sheet.set_cell_value("A1", "bad")

    with pytest.raises(ValidationError):
        readonly.save(tmp_path / "copy.xlsx")


def test_write_only_random_access_fail() -> None:
    """write_only 模式禁止随机写入。"""
    workbook = Workbook(mode="write_only")
    sheet = workbook.create_worksheet("Stream")
    with pytest.raises(ValidationError):
        sheet.set_cell_value("A1", 1)


def test_worksheet_insert_image(tmp_path: Path) -> None:
    """Worksheet 应提供统一的图片插入入口。"""
    image_path = tmp_path / "picture.png"
    Image.new("RGB", (8, 8), color="blue").save(image_path)

    workbook = Workbook()
    sheet = workbook.active

    sheet.insert_image(str(image_path), "A1", width=16, height=16)
    assert len(sheet._worksheet._images) == 1

    sheet.insert_images_batch(
        [
            {"image": str(image_path), "cell": "B2"},
        ]
    )
    assert len(sheet._worksheet._images) == 2


def test_large_data_processor_stream_batches(tmp_path: Path) -> None:
    """LargeDataProcessor 应当支持逐行迭代与批量策略。"""
    processor = LargeDataProcessor()
    output_path = tmp_path / "batched.xlsx"

    def row_generator() -> Iterator[dict[str, int]]:
        """生成测试数据行。"""
        for i in range(10):
            yield {"col_a": i, "col_b": i * 2}

    stats = processor.export_large_dataset(
        row_generator(),
        output_path,
        format_type=DataFormat.EXCEL,
        headers=["col_a", "col_b"],
        batch_size=3,
        memory_strategy=MemoryStrategy.BATCHED,
    )

    assert stats.rows_processed == 11  # header + 10 rows
    workbook = Workbook.load(output_path)
    sheet = workbook.get_worksheet("Sheet1")
    assert sheet is not None
    values = sheet.get_range_values("A1:B11")
    assert values[0] == ["col_a", "col_b"]
    assert values[5] == [4, 8]


def test_memory_optimized_workbook_streaming() -> None:
    """MemoryOptimizedWorkbook 应该采用 write_only 流式写入。"""
    dataset = [{"name": f"user_{i}", "score": i} for i in range(50)]

    optimized = MemoryOptimizedWorkbook()
    optimized.create_sheet_with_streaming(
        "Scores",
        dataset,
        headers=["name", "score"],
        batch_size=10,
    )
    data = optimized.to_bytes()
    optimized.cleanup()

    loaded = Workbook.from_bytes(data)
    sheet = loaded.get_worksheet("Scores")
    assert sheet is not None
    assert sheet.get_cell_value("A1") == "name"
    assert sheet.get_cell_value("B2") == 0
    assert sheet.get_cell_value("A51") == "user_49"
