from pathlib import Path

import pytest
from alembic import command
from alembic.config import Config
from fastapi.testclient import TestClient
from sqlalchemy import create_engine

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


def _make_app_alembic_config(database_url: str) -> Config:
    config = Config("alembic_app.ini")
    config.set_main_option("sqlalchemy.url", database_url)
    return config


@pytest.fixture
def test_database_urls(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
    app_database_path = tmp_path / "app_test.db"
    app_database_url = f"sqlite:///{app_database_path}"

    monkeypatch.setenv("APP_DATABASE_URL", app_database_url)
    monkeypatch.setenv("AUTH_BOOTSTRAP_USERNAME", "admin")
    monkeypatch.setenv("AUTH_BOOTSTRAP_PASSWORD", "test-password")
    monkeypatch.setenv("AUTH_COOKIE_SECURE_OVERRIDE", "false")
    # Disable throttle by default so existing tests are unaffected; throttle
    # tests opt in explicitly via their own monkeypatch / env override.
    monkeypatch.setenv("AUTH_LOGIN_THROTTLE_ENABLED", "false")
    get_settings.cache_clear()
    reset_db_caches()

    try:
        yield {
            "app_path": app_database_path,
            "app_url": app_database_url,
        }
    finally:
        get_settings.cache_clear()
        reset_db_caches()


@pytest.fixture
def auth_database(test_database_urls, monkeypatch: pytest.MonkeyPatch):
    database_url = test_database_urls["app_url"]
    command.upgrade(_make_app_alembic_config(database_url), "head")
    reset_db_caches()

    yield test_database_urls
    reset_db_caches()


@pytest.fixture
def app(auth_database):
    yield create_app()


@pytest.fixture
def client(app):
    with TestClient(app) as test_client:
        yield test_client


@pytest.fixture
def location_client(auth_database):
    app_url = auth_database["app_url"]
    engine = create_engine(app_url, connect_args={"check_same_thread": False})
    fastapi_app = create_app()
    with TestClient(fastapi_app) as client:
        yield client, engine
    engine.dispose()


@pytest.fixture
def poo_client(auth_database):
    app_url = auth_database["app_url"]
    engine = create_engine(app_url, connect_args={"check_same_thread": False})
    fastapi_app = create_app()
    with TestClient(fastapi_app) as client:
        yield client, engine
    engine.dispose()
