"""Refresh helper for mv_layout_velocity (Issue #113 PR B).

Not scheduled automatically in this PR — intended for manual invocation or
a Celery beat task in a follow-up issue.

Usage example (manual, via psql-connected shell or admin endpoint):
    from sqlalchemy.orm import Session
    from app.services.site_finder.layout_velocity_refresh import refresh_layout_velocity

    count = refresh_layout_velocity(db)
    # logs: "mv_layout_velocity refreshed: 459 rows"
"""

from __future__ import annotations

import logging

from sqlalchemy import text
from sqlalchemy.exc import OperationalError
from sqlalchemy.orm import Session

logger = logging.getLogger(__name__)


def refresh_layout_velocity(db: Session, *, concurrently: bool = True) -> int:
    """REFRESH MATERIALIZED VIEW mv_layout_velocity.

    Args:
        db: SQLAlchemy Session (sync).
        concurrently: When True, uses REFRESH CONCURRENTLY — non-blocking but
            requires the unique index mv_layout_velocity_pk to exist (created
            by 94_mv_layout_velocity.sql).  Pass False only for the very first
            populate or when the MV was just recreated.

    Returns:
        Row count in the MV after refresh (for observability / alerting).
    """
    try:
        if concurrently:
            db.execute(text("REFRESH MATERIALIZED VIEW CONCURRENTLY mv_layout_velocity"))
        else:
            db.execute(text("REFRESH MATERIALIZED VIEW mv_layout_velocity"))
        db.commit()
    except OperationalError as e:
        if concurrently and "cannot refresh materialized view" in str(e).lower():
            logger.warning(
                "CONCURRENTLY failed (MV likely not populated), falling back to non-concurrent"
            )
            db.rollback()
            db.execute(text("REFRESH MATERIALIZED VIEW mv_layout_velocity"))
            db.commit()
        else:
            raise
    row = db.execute(text("SELECT COUNT(*) FROM mv_layout_velocity")).first()
    count = int(row[0]) if row else 0
    logger.info("mv_layout_velocity refreshed: %d rows", count)
    return count
