"""Shared test fixtures using SQLite for fast, isolated tests."""
import asyncio
from collections.abc import AsyncGenerator

import pytest
from httpx import ASGITransport, AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine

from app.database import get_db
from app.main import app
from app.models.base import Base
from app.models.drug import Drug
from app.models.interaction import Interaction
from app.models.supplement import Supplement
from app.models.user_cabinet import UserCabinet

# Use an in-memory SQLite database for tests
TEST_DATABASE_URL = "sqlite+aiosqlite:///:memory:"

engine = create_async_engine(TEST_DATABASE_URL, echo=False)
TestSessionLocal = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)


@pytest.fixture(scope="session")
def event_loop():
    loop = asyncio.new_event_loop()
    yield loop
    loop.close()


@pytest.fixture(autouse=True)
async def setup_database():
    """Create all tables before each test, drop after."""
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)
    yield
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.drop_all)


@pytest.fixture
async def db_session() -> AsyncGenerator[AsyncSession, None]:
    async with TestSessionLocal() as session:
        yield session


@pytest.fixture
async def client(db_session: AsyncSession) -> AsyncGenerator[AsyncClient, None]:
    """HTTP test client with DB dependency overridden."""

    async def override_get_db():
        yield db_session

    app.dependency_overrides[get_db] = override_get_db
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as c:
        yield c
    app.dependency_overrides.clear()


@pytest.fixture
async def sample_drugs(db_session: AsyncSession) -> list[Drug]:
    """Insert sample drugs for testing."""
    drugs = [
        Drug(
            item_seq="200001234",
            item_name="Aspirin 100mg",
            slug="aspirin-100mg",
            company_name="PharmaCo",
            ingredients={"acetylsalicylic_acid": "100mg"},
            efficacy="Pain relief, fever reduction",
        ),
        Drug(
            item_seq="200005678",
            item_name="Warfarin 5mg",
            slug="warfarin-5mg",
            company_name="MedCorp",
            ingredients={"warfarin_sodium": "5mg"},
            efficacy="Anticoagulant",
        ),
    ]
    db_session.add_all(drugs)
    await db_session.commit()
    for d in drugs:
        await db_session.refresh(d)
    return drugs


@pytest.fixture
async def sample_interaction(db_session: AsyncSession, sample_drugs: list[Drug]) -> Interaction:
    """Insert a sample interaction between the two sample drugs."""
    interaction = Interaction(
        item_a="200001234",
        item_b="200005678",
        severity="high",
        description="Aspirin increases the anticoagulant effect of Warfarin, raising bleeding risk.",
        mechanism="Aspirin inhibits platelet aggregation and may displace Warfarin from protein binding sites.",
        recommendation="Avoid combination or monitor INR closely. Consult physician.",
        source="DrugBank",
    )
    db_session.add(interaction)
    await db_session.commit()
    await db_session.refresh(interaction)
    return interaction
