"""
批量操作测试
"""
import pytest
from tortoise import Tortoise

from fastapi_tortoise_crud import BaseModel
from fastapi_tortoise_crud.bulk import BulkOperations
from fastapi_tortoise_crud.model import fields


# 测试模型
class BulkTestModel(BaseModel):
    name = fields.CharField(max_length=50, description="名称")
    value = fields.IntField(description="值")
    
    class Meta:
        table = "bulk_test_models"


@pytest.fixture
async def init_db():
    """初始化数据库"""
    await Tortoise.init(
        db_url='sqlite://:memory:',
        modules={'models': ['tests.test_bulk']}
    )
    await Tortoise.generate_schemas()
    yield
    await Tortoise.close_connections()


@pytest.mark.asyncio
async def test_bulk_create(init_db):
    """测试批量创建"""
    # 准备测试数据
    items = [
        {"name": f"test{i}", "value": i}
        for i in range(5)
    ]
    
    # 批量创建
    results = await BulkOperations.bulk_create(BulkTestModel, items)
    
    # 验证结果
    assert len(results) == 5
    for i, result in enumerate(results):
        assert result.name == f"test{i}"
        assert result.value == i
        assert result.status is True
        assert result.version == 1


@pytest.mark.asyncio
async def test_bulk_update(init_db):
    """测试批量更新"""
    # 创建测试数据
    items = [
        {"name": f"test{i}", "value": i}
        for i in range(5)
    ]
    original_models = await BulkOperations.bulk_create(BulkTestModel, items)
    
    # 准备更新数据
    updates = [
        {
            "id": model.id,
            "value": model.value + 10
        }
        for model in original_models
    ]
    
    # 批量更新
    updated_count = await BulkOperations.bulk_update(
        BulkTestModel,
        updates,
        fields=['value']
    )
    
    # 验证结果
    assert updated_count == 5
    updated_models = await BulkTestModel.all()
    for i, model in enumerate(updated_models):
        assert model.value == i + 10
        assert model.version == 2  # 版本号应该增加


@pytest.mark.asyncio
async def test_bulk_delete(init_db):
    """测试批量删除（禁用）"""
    # 创建测试数据
    items = [
        {"name": f"test{i}", "value": i}
        for i in range(5)
    ]
    models = await BulkOperations.bulk_create(BulkTestModel, items)
    
    # 获取ID列表
    ids = [model.id for model in models]
    
    # 批量禁用
    deleted_count = await BulkOperations.bulk_delete(
        BulkTestModel,
        {'id__in': ids}
    )
    
    # 验证结果
    assert deleted_count == 5
    
    # 验证记录已被禁用
    for model_id in ids:
        model = await BulkTestModel.get_or_none(id=model_id)
        assert model.status is False
    
    # 验证查询时会过滤掉已禁用的记录
    remaining = await BulkTestModel.find_by()
    assert len(remaining) == 0


@pytest.mark.asyncio
async def test_bulk_physical_delete(init_db):
    """测试批量物理删除"""
    # 创建测试数据
    items = [
        {"name": f"test{i}", "value": i}
        for i in range(5)
    ]
    models = await BulkOperations.bulk_create(BulkTestModel, items)
    
    # 获取ID列表
    ids = [model.id for model in models]
    
    # 批量物理删除
    deleted_count = await BulkOperations.bulk_delete(
        BulkTestModel,
        {'id__in': ids},
        physical_delete=True
    )
    
    # 验证结果
    assert deleted_count == 5
    
    # 验证记录已被物理删除
    for model_id in ids:
        model = await BulkTestModel.get_or_none(id=model_id)
        assert model is None


@pytest.mark.asyncio
async def test_bulk_get(init_db):
    """测试批量获取"""
    # 创建测试数据
    items = [
        {"name": f"test{i}", "value": i, "status": i % 2 == 0}
        for i in range(5)
    ]
    original_models = await BulkOperations.bulk_create(BulkTestModel, items)
    
    # 获取ID列表
    ids = [model.id for model in original_models]
    
    # 测试只获取启用的记录
    results = await BulkOperations.bulk_get(BulkTestModel, ids)
    assert len(results) == 3  # 只有status为True的记录
    
    # 测试获取所有记录
    results = await BulkOperations.bulk_get(BulkTestModel, ids, include_disabled=True)
    assert len(results) == 5  # 所有记录


@pytest.mark.asyncio
async def test_bulk_create_with_conflicts(init_db):
    """测试带冲突处理的批量创建"""
    # 创建初始数据
    items = [
        {"name": "test1", "value": 1},
        {"name": "test2", "value": 2}
    ]
    await BulkOperations.bulk_create(BulkTestModel, items)
    
    # 尝试创建包含冲突的数据
    conflict_items = [
        {"name": "test1", "value": 3},  # 冲突
        {"name": "test3", "value": 3}   # 新数据
    ]
    
    # 使用ignore_conflicts=True
    results = await BulkOperations.bulk_create(
        BulkTestModel,
        conflict_items,
        ignore_conflicts=True
    )
    
    # 验证结果
    all_models = await BulkTestModel.all()
    assert len(all_models) == 3  # 应该有3条记录
    
    # 验证值没有被覆盖
    model = await BulkTestModel.get(name="test1")
    assert model.value == 1  # 原始值应该保持不变 