"""Explicit target selection for schema migrations.

Migrations never inherit a database from .env. The operator must name the target twice:
DATABASE_URL in the process environment, and ALEMBIC_TARGET_DB with the same database name.
A database whose name contains "primary" additionally needs ALEMBIC_ALLOW_PRIMARY=1.
"""

from __future__ import annotations

from collections.abc import Mapping

from sqlalchemy.engine import make_url


class MigrationTargetError(RuntimeError):
    pass


def resolve_migration_url(environ: Mapping[str, str]) -> str:
    raw = environ.get("DATABASE_URL", "").strip()
    if not raw:
        raise MigrationTargetError(
            "DATABASE_URL must be set explicitly in the environment; "
            ".env is not used for migrations"
        )
    try:
        name = make_url(raw).database or ""
    except Exception as exc:
        raise MigrationTargetError("DATABASE_URL is not a valid URL") from exc
    if not name:
        raise MigrationTargetError("DATABASE_URL names no database")

    expected = environ.get("ALEMBIC_TARGET_DB", "").strip()
    if not expected:
        raise MigrationTargetError("ALEMBIC_TARGET_DB must name the target database")
    if expected != name:
        raise MigrationTargetError(
            f"ALEMBIC_TARGET_DB ({expected!r}) does not match DATABASE_URL's database ({name!r})"
        )
    if "primary" in name.lower() and environ.get("ALEMBIC_ALLOW_PRIMARY") != "1":
        raise MigrationTargetError(
            f"{name!r} looks like a primary database; set ALEMBIC_ALLOW_PRIMARY=1 to migrate it"
        )
    return raw
