"""پیکربندی مشترک تست‌ها (pytest).

تست‌ها روی SQLite (aiosqlite) اجرا می‌شوند تا نیازی به PostgreSQL/Redis
واقعی نباشد. متغیرهای محیطی پیش از import ماژول‌های برنامه تنظیم می‌شوند تا
engine و session با SQLite ساخته شوند.
"""
from __future__ import annotations

import os
from contextlib import asynccontextmanager

# --- تنظیم محیط تست پیش از هر import از برنامه ---
os.environ["ENVIRONMENT"] = "test"
os.environ["AUTH_REQUIRED"] = "false"
os.environ["DATABASE_URL"] = "sqlite+aiosqlite:///./test_core.db"
os.environ["DATABASE_URL_SYNC"] = "sqlite:///./test_core.db"
os.environ["KEYCLOAK_ENABLED"] = "false"
os.environ["JWT_VERIFY_SIGNATURE"] = "false"
os.environ["JWT_SECRET"] = "test-jwt-secret"

import pytest_asyncio  # noqa: E402
from httpx import ASGITransport, AsyncClient  # noqa: E402

import app.models  # noqa: E402,F401  (ثبت مدل‌ها روی metadata)
from app.core.cache import cache  # noqa: E402
from app.core.database import AsyncSessionLocal, Base, engine  # noqa: E402
from app.main import app  # noqa: E402

# در تست‌ها Redis در دسترس نیست؛ cache را غیرفعال می‌کنیم (fail-open).
cache.disable()


@asynccontextmanager
async def _test_lifespan(_app):
    """No-op lifespan so ASGITransport teardown does not hang."""
    yield


# Override FastAPI lifespan for in-process tests (httpx 0.27 has no lifespan=off).
app.router.lifespan_context = _test_lifespan


@pytest_asyncio.fixture
async def db_setup():
    """ساخت و پاک‌سازی اسکیمای دیتابیس برای هر تست (ایزوله)."""
    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)
    # Prevent aiosqlite connection hang on Windows teardown
    await engine.dispose()


@pytest_asyncio.fixture
async def client(db_setup):
    """کلاینت HTTP async برای فراخوانی API درون‌فرآیندی."""
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
        yield ac
    await engine.dispose()


@pytest_asyncio.fixture
async def session(db_setup):
    """یک AsyncSession برای تست‌های سطح سرویس/repository."""
    async with AsyncSessionLocal() as s:
        yield s
    await engine.dispose()
