import asyncio
from contextlib import contextmanager
import os

import pytest
from fastapi.testclient import TestClient


from src.db.base import SessionLocal
from src.db.session import get_db
from src.main import app


            
@pytest.fixture
def client():
    db_ref = SessionLocal()
    loop_ref = None

    async def _get_db():
        nonlocal loop_ref
        loop_ref = asyncio.get_running_loop()
        try:
            yield db_ref
            await db_ref.flush()
        except:
            await db_ref.rollback()
            raise

    app.dependency_overrides[get_db] = _get_db
    with TestClient(app) as test_client:
        try:
            yield test_client
        finally:
            if db_ref is not None and loop_ref:
                async def cleanup():
                    await db_ref.rollback()
                    await db_ref.close()

                future = asyncio.run_coroutine_threadsafe(cleanup(), loop_ref)
                future.result()
            app.dependency_overrides.clear()


@pytest.fixture
def admin_password() -> str:
    # Пароль админа берём из окружения, чтобы не хардкодить локальные отличия.
    return os.getenv("OPENBAO__TEST_ADMIN_PASSWORD", "admin123")


@pytest.fixture
def isp_password() -> str:
    # Пароль админа берём из окружения, чтобы не хардкодить локальные отличия.
    return os.getenv("OPENBAO__TEST_EXECUTOR_PASSWORD", "admin123")


@pytest.fixture
def admin_tokens(client, admin_password: str):
    response = client.post(
        "/api/v1/auth/login",
        json={"username": "admin", "password": admin_password},
    )
    assert response.status_code == 200
    return response.json()


@pytest.fixture
def auth_headers():
    def _build(tokens: dict) -> dict:
        return {"Authorization": f"Bearer {tokens['access_token']}"}

    return _build

@pytest.fixture
def isp_tokens(client, isp_password: str):
    response = client.post(
        "/api/v1/auth/login",
        json={"username": "isp1", "password": isp_password},
    )
    assert response.status_code == 200
    return response.json()
