from pathlib import Path

import pytest
from alembic import command
from alembic.config import Config
from sqlalchemy import create_engine, text
from sqlalchemy.engine import make_url
from sqlalchemy.orm import sessionmaker

import flyway.models  # noqa: F401
from flyway.config import settings
from flyway.db import Base

TEST_URL = settings.test_database_url
BACKEND_DIR = Path(__file__).resolve().parents[1]


def _recreate_database(url: str) -> None:
    u = make_url(url)
    admin = create_engine(u.set(database="postgres"), isolation_level="AUTOCOMMIT")
    with admin.connect() as c:
        c.execute(text(f'DROP DATABASE IF EXISTS "{u.database}" WITH (FORCE)'))
        c.execute(text(f"CREATE DATABASE \"{u.database}\" ENCODING 'UTF8' TEMPLATE template0"))
    admin.dispose()


@pytest.fixture(scope="session")
def engine():
    _recreate_database(TEST_URL)
    cfg = Config(str(BACKEND_DIR / "alembic.ini"))
    cfg.set_main_option("script_location", str(BACKEND_DIR / "migrations"))
    cfg.set_main_option("sqlalchemy.url", TEST_URL)
    command.upgrade(cfg, "head")
    eng = create_engine(TEST_URL)
    yield eng
    eng.dispose()


@pytest.fixture
def factory(engine):
    f = sessionmaker(engine, expire_on_commit=False)
    yield f
    names = ", ".join(f'"{t.name}"' for t in Base.metadata.sorted_tables)
    with engine.begin() as c:
        c.execute(text(f"TRUNCATE {names} RESTART IDENTITY CASCADE"))


@pytest.fixture
def db(factory):
    with factory() as s:
        yield s
        s.rollback()

from tests.api_client import admin_api, staff_api  # noqa: E402,F401
