"""Shared fixtures.

DB-backed tests run against the real Postgres sidecar (inside the app
container: `docker exec garden2-app sh -c "pip install pytest && python -m
pytest"`), wrapped in an outer transaction that ALWAYS rolls back — the
migrated data is never dirtied. When DATABASE_URL is absent (host runs
without the sidecar reachable), DB tests skip; pure-unit suites still run.
"""
from __future__ import annotations

import os

import pytest

# BW Auth (Pattern B) app-session secret used across the suite.
SECRET = "test-session-secret-for-suite"


def session_cookie(user: str = "rian", ttl: int = 3600) -> str:
    """A signed app-session cookie value for `user` (mirrors the callback)."""
    from app.app_session import sign_session

    return sign_session(user, SECRET, ttl)


@pytest.fixture()
def auth_headers() -> dict:
    """Authenticate a TestClient request via the app-session cookie. Sent as a
    Cookie header so `headers=auth_headers` keeps working across the suite."""
    from app.app_session import SESSION_COOKIE

    return {"Cookie": f"{SESSION_COOKIE}={session_cookie()}"}


@pytest.fixture()
def app_client(monkeypatch):
    """TestClient with BW Auth (PUBLIC mode) configured; DB routes require
    DATABASE_URL. BW_CLIENT_ID is set so the app is 'configured' but no test
    triggers a real network call to id-auth (the silent probe only fires on
    an unauthenticated HTML GET, which these API tests don't make)."""
    from starlette.testclient import TestClient

    from app.config import get_settings
    from app.main import create_app

    monkeypatch.setenv("APP_SESSION_SECRET", SECRET)
    monkeypatch.setenv("BW_CLIENT_ID", "garden2-test")
    monkeypatch.setenv("BW_APP_DOMAIN", "https://garden2.test")
    monkeypatch.setenv("DOMAIN_MODE", "public")
    get_settings.cache_clear()
    app = create_app()
    with TestClient(app, raise_server_exceptions=False) as c:
        yield c
    get_settings.cache_clear()


@pytest.fixture()
def db_session():
    """SAVEPOINT-wrapped session on the real DB; always rolls back."""
    if not os.environ.get("DATABASE_URL"):
        pytest.skip("DATABASE_URL not set — DB tests run in-container")
    from sqlalchemy import create_engine
    from sqlalchemy.orm import Session

    engine = create_engine(os.environ["DATABASE_URL"])
    connection = engine.connect()
    txn = connection.begin()
    session = Session(bind=connection, join_transaction_mode="create_savepoint")
    try:
        yield session
    finally:
        session.close()
        txn.rollback()
        connection.close()
        engine.dispose()
