"""
集成测试
需要真实数据库连接，使用 --run-integration 参数运行
"""
import pytest
from xll_kit.database import (
    MySQLBuilder,
    PostgreSQLBuilder,
    SQLExecutor,
    DatabaseManager,
)


@pytest.mark.integration
class TestSQLiteIntegration:
    """SQLite 集成测试（使用内存数据库）"""

    def test_full_workflow_with_executor(self, in_memory_executor, sample_user):
        """测试完整工作流 - Executor 方式"""
        executor = in_memory_executor
        builder = PostgreSQLBuilder()  # SQLite 使用 PostgreSQL 语法

        # 1. 插入
        table = executor.get_table('users')
        sql_result = builder.build_insert(table, sample_user)
        affected = executor.execute(sql_result)
        assert affected == 1

        # 2. 查询
        results = executor.query(
            "SELECT * FROM users WHERE email = :email",
            {'email': sample_user['email']}
        )
        assert len(results) == 1
        assert results[0]['name'] == sample_user['name']

        # 3. 更新
        update_data = {'name': 'Updated Name'}
        where = {'email': sample_user['email']}
        sql_result = builder.build_update(table, update_data, where)
        affected = executor.execute(sql_result)
        assert affected == 1

        # 4. 验证更新
        result = executor.query_one(
            "SELECT * FROM users WHERE email = :email",
            {'email': sample_user['email']}
        )
        assert result['name'] == 'Updated Name'

        # 5. 删除
        sql_result = builder.build_delete(table, {'email': sample_user['email']})
        affected = executor.execute(sql_result)
        assert affected == 1

        # 6. 验证删除
        results = executor.query("SELECT * FROM users")
        assert len(results) == 0

    def test_batch_operations(self, in_memory_executor, sample_users):
        """测试批量操作"""
        executor = in_memory_executor
        builder = PostgreSQLBuilder()
        table = executor.get_table('users')

        # 1. 批量插入
        sql_result = builder.build_batch_insert(table, sample_users)
        affected = executor.execute(sql_result)
        assert affected == len(sample_users)

        # 2. 查询验证
        results = executor.query("SELECT * FROM users ORDER BY age")
        assert len(results) == len(sample_users)

        # 3. 批量更新
        update_list = [
            {'email': user['email'], 'age': user['age'] + 1}
            for user in sample_users
        ]
        sql_result = builder.build_batch_update(table, update_list, ['email'])
        affected = executor.execute(sql_result)
        assert affected > 0

        # 4. 验证更新
        results = executor.query("SELECT * FROM users WHERE email = :email",
                                 {'email': sample_users[0]['email']})
        assert results[0]['age'] == sample_users[0]['age'] + 1

    def test_upsert_operations(self, in_memory_executor, sample_user):
        """测试 Upsert 操作"""
        executor = in_memory_executor
        builder = PostgreSQLBuilder()
        table = executor.get_table('users')

        # 1. 首次插入
        sql_result = builder.build_upsert(table, sample_user, ['email'])
        affected = executor.execute(sql_result)
        assert affected == 1

        # 2. Upsert（更新）
        updated_user = sample_user.copy()
        updated_user['name'] = 'Updated via Upsert'
        updated_user['age'] = 99

        sql_result = builder.build_upsert(table, updated_user, ['email'])
        affected = executor.execute(sql_result)
        assert affected >= 1

        # 3. 验证更新
        result = executor.query_one(
            "SELECT * FROM users WHERE email = :email",
            {'email': sample_user['email']}
        )
        assert result['name'] == 'Updated via Upsert'
        assert result['age'] == 99


@pytest.mark.integration
@pytest.mark.slow
class TestMySQLIntegration:
    """MySQL 集成测试（需要真实 MySQL 数据库）"""

    @pytest.fixture(scope="class")
    def mysql_executor(self, test_database_uri):
        """创建 MySQL Executor"""
        if 'mysql' not in test_database_uri:
            pytest.skip("需要 MySQL 数据库")

        executor = SQLExecutor(test_database_uri)
        yield executor
        executor.close()

    def test_mysql_insert_and_query(self, mysql_executor, sample_user):
        """测试 MySQL 插入和查询"""
        builder = MySQLBuilder()
        table = mysql_executor.get_table('test_users')

        # 插入
        sql_result = builder.build_insert(table, sample_user)
        affected = mysql_executor.execute(sql_result)
        assert affected == 1

        # 查询
        results = mysql_executor.query(
            "SELECT * FROM test_users WHERE email = :email",
            {'email': sample_user['email']}
        )
        assert len(results) >= 1

        # 清理
        mysql_executor.execute(
            builder.build_delete(table, {'email': sample_user['email']})
        )

    def test_mysql_upsert(self, mysql_executor, sample_user):
        """测试 MySQL ON DUPLICATE KEY UPDATE"""
        builder = MySQLBuilder()
        table = mysql_executor.get_table('test_users')

        # 首次插入
        sql_result = builder.build_upsert(table, sample_user, ['email'])
        mysql_executor.execute(sql_result)

        # Upsert 更新
        updated = sample_user.copy()
        updated['age'] = 100
        sql_result = builder.build_upsert(table, updated, ['email'])
        mysql_executor.execute(sql_result)

        # 验证
        result = mysql_executor.query_one(
            "SELECT * FROM test_users WHERE email = :email",
            {'email': sample_user['email']}
        )
        assert result['age'] == 100

        # 清理
        mysql_executor.execute(
            builder.build_delete(table, {'email': sample_user['email']})
        )


@pytest.mark.integration
class TestDatabaseManagerIntegration:
    """DatabaseManager 集成测试"""

    def test_manager_full_workflow(self, in_memory_engine, sample_user):
        """测试 Manager 完整工作流"""
        # 注意：这里使用 SQLite 内存数据库
        manager = DatabaseManager('sqlite:///:memory:')
        manager._engine = in_memory_engine
        manager._metadata.reflect(bind=in_memory_engine)
        manager._table_cache = {}

        try:
            # 1. 插入
            affected = manager.insert('users', sample_user)
            assert affected == 1

            # 2. 查询
            results = manager.query("SELECT * FROM users")
            assert len(results) == 1

            # 3. 更新
            affected = manager.update(
                'users',
                {'name': 'New Name'},
                {'email': sample_user['email']}
            )
            assert affected == 1

            # 4. 删除
            affected = manager.delete('users', {'email': sample_user['email']})
            assert affected == 1

        finally:
            manager.close()

    def test_manager_batch_operations(self, in_memory_engine, sample_users):
        """测试 Manager 批量操作"""
        manager = DatabaseManager('sqlite:///:memory:')
        manager._engine = in_memory_engine
        manager._metadata.reflect(bind=in_memory_engine)
        manager._table_cache = {}

        try:
            # 批量插入
            affected = manager.insert_many('users', sample_users)
            assert affected == len(sample_users)

            # 查询验证
            results = manager.query("SELECT * FROM users")
            assert len(results) == len(sample_users)

            # Upsert
            updated_users = [
                {**user, 'age': user['age'] + 10}
                for user in sample_users
            ]
            affected = manager.upsert_many('users', updated_users, ['email'])
            assert affected >= len(sample_users)

        finally:
            manager.close()

    def test_manager_context_manager(self, in_memory_engine, sample_user):
        """测试 Manager 作为上下文管理器"""
        with DatabaseManager('sqlite:///:memory:') as manager:
            manager._engine = in_memory_engine
            manager._metadata.reflect(bind=in_memory_engine)
            manager._table_cache = {}

            # 执行操作
            affected = manager.insert('users', sample_user)
            assert affected == 1

        # 退出上下文后应该已关闭连接
        # 这里无法直接验证，但不应该抛出异常


@pytest.mark.integration
@pytest.mark.slow
class TestLargeDatasetIntegration:
    """大数据集集成测试"""

    def test_large_batch_insert(self, in_memory_executor, large_dataset):
        """测试大批量插入"""
        builder = PostgreSQLBuilder()
        table = in_memory_executor.get_table('users')

        # 分批插入（每批100条）
        batch_size = 100
        total_affected = 0

        for i in range(0, len(large_dataset), batch_size):
            batch = large_dataset[i:i + batch_size]
            sql_result = builder.build_batch_insert(table, batch)
            affected = in_memory_executor.execute(sql_result)
            total_affected += affected

        assert total_affected == len(large_dataset)

        # 验证
        results = in_memory_executor.query("SELECT COUNT(*) as count FROM users")
        assert results[0]['count'] == len(large_dataset)