# conftest.py
from typing import Generator, Callable, Any
import pytest
from testcontainers.postgres import PostgresContainer
from fastapi.testclient import TestClient
from core.config import settings
from faker import Faker
from sqlalchemy.orm import Session

from core.database import get_db, get_sessionmaker


fake = Faker()


@pytest.fixture(scope="session")
def postgres_container() -> Generator[PostgresContainer, None, None]:
    """Fixture to create a PostgreSQL container for testing."""
    print("Starting Postgres container...")
    with PostgresContainer("postgres:latest") as postgres:
        settings.DB_URL = postgres.get_connection_url()
        print(f"Postgres container started at {settings.DB_URL}")
        yield postgres
    print("Postgres container stopped.")


@pytest.fixture(scope="function")
def db(postgres_container) -> Generator[Session, None, None]:
    """Function-scoped database session with rollback"""
    SessionLocal = get_sessionmaker()
    session = SessionLocal()
    session.begin_nested()  # Enable nested transaction
    try:
        yield session
    finally:
        session.rollback()
        session.close()


@pytest.fixture(scope="function")
def client(db: Session) -> Generator[TestClient, None, None]:
    """Function-scoped test client with dependency override"""
    from main import app

    # Override the database dependency
    def override_get_db():
        try:
            yield db
        finally:
            pass  # Don't close session here

    app.dependency_overrides[get_db] = override_get_db

    with TestClient(app) as test_client:
        yield test_client

    app.dependency_overrides.clear()


def override_dependency(dependency: Callable[..., Any], mocked_response: Any) -> None:
    from main import app

    app.dependency_overrides[dependency] = lambda: mocked_response
