from __future__ import annotations

import argparse
import sys
import time

from govoplan_core.db.migrations import (
    configured_migration_heads,
    database_migration_heads,
)
from govoplan_core.settings import settings


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        description="Wait until the database is at this release's migration heads."
    )
    parser.add_argument("--database-url", default=settings.database_url)
    parser.add_argument(
        "--migration-track",
        default=settings.migration_track,
        choices=("release", "dev"),
    )
    parser.add_argument("--timeout-seconds", type=float, default=900.0)
    parser.add_argument("--poll-seconds", type=float, default=2.0)
    return parser


def main(argv: list[str] | None = None) -> int:
    args = build_parser().parse_args(argv)
    if args.timeout_seconds < 0 or args.poll_seconds <= 0:
        raise SystemExit("timeouts must be non-negative and polling must be positive")
    expected = configured_migration_heads(
        args.database_url,
        migration_track=args.migration_track,
    )
    deadline = time.monotonic() + args.timeout_seconds
    last_error = ""
    while True:
        try:
            actual = database_migration_heads(args.database_url)
            if actual == expected:
                print("Database migration heads are ready: " + ",".join(actual))
                return 0
            last_error = (
                f"database heads={','.join(actual) or '<none>'}; "
                f"expected={','.join(expected) or '<none>'}"
            )
        except Exception as exc:  # noqa: BLE001 - connection may become ready later
            last_error = f"{type(exc).__name__}: {exc}"
        if time.monotonic() >= deadline:
            print(
                "Database did not reach configured migration heads: " + last_error,
                file=sys.stderr,
            )
            return 75
        time.sleep(min(args.poll_seconds, max(0.05, deadline - time.monotonic())))


if __name__ == "__main__":
    raise SystemExit(main())
