"""
Pytest 配置文件
提供全局 fixtures 和配置
"""
import pytest
import os
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
from sqlalchemy.pool import StaticPool

from xll_kit.database import SQLExecutor


# ==================== 全局配置 ====================

@pytest.fixture(scope="session")
def test_database_uri():
    """测试数据库 URI"""
    return os.getenv(
        'TEST_DATABASE_URI',
        'mysql+pymysql://root:password@localhost:3306/test_xll_kit'
    )


@pytest.fixture(scope="session")
def sqlite_memory_uri():
    """SQLite 内存数据库（用于快速测试）"""
    return 'sqlite:///:memory:'


# ==================== 数据库 Fixtures ====================

@pytest.fixture(scope="function")
def in_memory_engine():
    """创建内存数据库引擎"""
    engine = create_engine(
        'sqlite:///:memory:',
        connect_args={'check_same_thread': False},
        poolclass=StaticPool
    )

    # 创建测试表
    metadata = MetaData()
    Table(
        'users',
        metadata,
        Column('id', Integer, primary_key=True, autoincrement=True),
        Column('name', String(50)),
        Column('email', String(100), unique=True),
        Column('age', Integer),
    )
    metadata.create_all(engine)

    yield engine

    engine.dispose()


@pytest.fixture(scope="function")
def in_memory_executor(in_memory_engine):
    """创建基于内存数据库的 Executor"""
    executor = SQLExecutor(
        database_uri='sqlite:///:memory:',
        echo=False
    )
    # 替换为已创建的内存引擎
    executor._engine = in_memory_engine
    executor._metadata = MetaData()
    executor._metadata.reflect(bind=in_memory_engine)

    yield executor

    executor.close()


# ==================== 测试数据 Fixtures ====================

@pytest.fixture
def sample_user():
    """单个用户数据"""
    return {
        'name': 'Alice',
        'email': 'alice@example.com',
        'age': 25
    }


@pytest.fixture
def sample_users():
    """多个用户数据"""
    return [
        {'name': 'Bob', 'email': 'bob@example.com', 'age': 30},
        {'name': 'Charlie', 'email': 'charlie@example.com', 'age': 28},
        {'name': 'David', 'email': 'david@example.com', 'age': 35},
        {'name': 'Eve', 'email': 'eve@example.com', 'age': 27},
    ]


@pytest.fixture
def large_dataset():
    """大数据集"""
    return [
        {
            'name': f'User{i}',
            'email': f'user{i}@example.com',
            'age': 20 + (i % 50)
        }
        for i in range(1000)
    ]


# ==================== 表结构 Fixtures ====================

@pytest.fixture
def mock_users_table():
    """模拟的 users 表"""
    metadata = MetaData()
    table = Table(
        'users',
        metadata,
        Column('id', Integer, primary_key=True),
        Column('name', String(50)),
        Column('email', String(100)),
        Column('age', Integer),
    )
    return table


@pytest.fixture
def mock_orders_table():
    """模拟的 orders 表"""
    metadata = MetaData()
    table = Table(
        'orders',
        metadata,
        Column('id', Integer, primary_key=True),
        Column('user_id', Integer),
        Column('product', String(100)),
        Column('quantity', Integer),
        Column('price', Integer),
    )
    return table


# ==================== 清理 Fixtures ====================

@pytest.fixture(scope="function", autouse=True)
def cleanup_test_data(in_memory_executor):
    """每个测试后清理数据"""
    yield

    # 测试结束后清理
    try:
        in_memory_executor.execute_sql(
            "DELETE FROM users",
            {}
        )
    except:
        pass


# ==================== 环境变量设置 ====================

@pytest.fixture(scope="session", autouse=True)
def setup_test_env():
    """设置测试环境变量"""
    os.environ['ENVIRONMENT'] = 'testing'
    os.environ['LOG_LEVEL'] = 'DEBUG'

    yield

    # 清理
    os.environ.pop('ENVIRONMENT', None)
    os.environ.pop('LOG_LEVEL', None)


# ==================== 日志配置 ====================

@pytest.fixture(scope="session", autouse=True)
def setup_test_logging():
    """配置测试日志"""
    import logging
    from xll_kit.utils import setup_logger

    # 配置测试日志
    setup_logger(
        name='xll_kit',
        level='WARNING',  # 测试时减少日志输出
        log_file=None,
        use_color=False
    )

    # 禁用 SQLAlchemy 日志
    logging.getLogger('sqlalchemy.engine').setLevel(logging.ERROR)


# ==================== Pytest Hooks ====================

def pytest_collection_modifyitems(config, items):
    """修改测试收集"""
    # 为慢速测试添加标记
    for item in items:
        if "integration" in item.keywords:
            item.add_marker(pytest.mark.slow)


def pytest_configure(config):
    """Pytest 配置"""
    # 注册自定义标记
    config.addinivalue_line(
        "markers",
        "integration: 集成测试，需要真实数据库"
    )
    config.addinivalue_line(
        "markers",
        "slow: 慢速测试"
    )
    config.addinivalue_line(
        "markers",
        "benchmark: 性能基准测试"
    )
    config.addinivalue_line(
        "markers",
        "unit: 单元测试"
    )


# ==================== 命令行选项 ====================

def pytest_addoption(parser):
    """添加自定义命令行选项"""
    parser.addoption(
        "--run-integration",
        action="store_true",
        default=False,
        help="运行集成测试（需要真实数据库连接）"
    )
    parser.addoption(
        "--run-slow",
        action="store_true",
        default=False,
        help="运行慢速测试"
    )
    parser.addoption(
        "--database-uri",
        action="store",
        default=None,
        help="指定测试数据库URI"
    )


def pytest_runtest_setup(item):
    """测试运行前的设置"""
    # 跳过集成测试（除非指定 --run-integration）
    if "integration" in item.keywords and not item.config.getoption("--run-integration"):
        pytest.skip("需要 --run-integration 选项")

    # 跳过慢速测试（除非指定 --run-slow）
    if "slow" in item.keywords and not item.config.getoption("--run-slow"):
        pytest.skip("需要 --run-slow 选项")


# ==================== 测试报告增强 ====================

@pytest.fixture(scope="function", autouse=True)
def print_test_info(request):
    """打印测试信息"""
    test_name = request.node.name
    print(f"\n{'=' * 60}")
    print(f"Running: {test_name}")
    print(f"{'=' * 60}")

    yield

    print(f"\n{'=' * 60}")
    print(f"Finished: {test_name}")
    print(f"{'=' * 60}")


# ==================== 性能测试辅助 ====================

@pytest.fixture
def benchmark_config():
    """性能测试配置"""
    return {
        'warmup_rounds': 3,
        'test_rounds': 10,
        'timeout': 60
    }


# ==================== 临时文件/目录 ====================

@pytest.fixture
def temp_log_dir(tmp_path):
    """临时日志目录"""
    log_dir = tmp_path / "logs"
    log_dir.mkdir()
    return log_dir


# ==================== 数据库连接池测试 ====================

@pytest.fixture
def connection_pool_config():
    """连接池配置"""
    return {
        'pool_size': 5,
        'max_overflow': 10,
        'pool_timeout': 30,
        'pool_recycle': 3600
    }


# ==================== Mock 辅助 ====================

@pytest.fixture
def mock_successful_execute():
    """模拟成功的执行结果"""
    from unittest.mock import MagicMock

    result = MagicMock()
    result.rowcount = 1
    result.fetchall.return_value = []
    result.keys.return_value = []
    return result


@pytest.fixture
def mock_query_result():
    """模拟查询结果"""
    from unittest.mock import MagicMock

    result = MagicMock()
    result.fetchall.return_value = [
        (1, 'Alice', 'alice@example.com', 25),
        (2, 'Bob', 'bob@example.com', 30)
    ]
    result.keys.return_value = ['id', 'name', 'email', 'age']
    return result