"""
Shared test fixtures for BaoLife/Lichun test suite.

Provides database setup, test data, and mock objects.
"""

import pytest
import asyncio
import os
import sys
from pathlib import Path

# Add ws directory to Python path for imports
ws_dir = Path(__file__).parent.parent / 'ws'
sys.path.insert(0, str(ws_dir))

# Set test mode before importing config
os.environ['TEST_MODE'] = 'true'
os.environ['DB_NAME'] = 'lifesim_test'  # Use test database

from ws.database_async import initialize_pool, close_pool, _pool
import aiomysql


@pytest.fixture(scope="session")
def event_loop():
    """Create an instance of the default event loop for the test session."""
    loop = asyncio.get_event_loop_policy().new_event_loop()
    yield loop
    loop.close()


@pytest.fixture(scope="session")
async def db_pool():
    """
    Session-scoped database connection pool for tests.

    Creates a pool at the start of the test session and closes it at the end.
    """
    # Initialize pool with smaller size for testing
    pool = await initialize_pool(pool_size=5)

    yield pool

    # Close pool after all tests
    await close_pool()


@pytest.fixture
async def db_connection(db_pool):
    """
    Function-scoped database connection.

    Provides a fresh connection for each test.
    """
    async with db_pool.acquire() as conn:
        yield conn


@pytest.fixture
async def db_transaction(db_pool):
    """
    Function-scoped database transaction that rolls back after test.

    Usage:
        async def test_something(db_transaction):
            conn = db_transaction
            async with conn.cursor() as cursor:
                await cursor.execute("INSERT INTO ...")
            # Automatically rolled back after test
    """
    async with db_pool.acquire() as conn:
        # Start transaction
        await conn.begin()

        yield conn

        # Rollback transaction (cleanup)
        await conn.rollback()


@pytest.fixture
async def test_table(db_connection):
    """
    Creates a temporary test table for testing.

    Returns the table name and cleans up after test.
    """
    table_name = "test_data"

    async with db_connection.cursor() as cursor:
        # Create test table
        await cursor.execute(f"""
            CREATE TABLE IF NOT EXISTS {table_name} (
                id INT AUTO_INCREMENT PRIMARY KEY,
                name VARCHAR(100),
                value INT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        """)
        await db_connection.commit()

    yield table_name

    # Cleanup: Drop test table
    async with db_connection.cursor() as cursor:
        await cursor.execute(f"DROP TABLE IF EXISTS {table_name}")
        await db_connection.commit()


@pytest.fixture
def cleanup_pool():
    """
    Cleanup fixture to ensure pool is reset between tests.

    This is useful for tests that need to test pool initialization.
    """
    yield

    # Reset global pool state
    import ws.database_async as db_async
    if db_async._pool is not None:
        loop = asyncio.get_event_loop()
        loop.run_until_complete(close_pool())
