"""Refresh helper for mv_quarter_price_per_m2 (Issue #33 D1).

Not scheduled automatically in this PR — intended for manual invocation or
a Celery beat task in a follow-up issue (Issue #33 PR C).

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

    count = refresh_quarter_price(db)
    # logs: "mv_quarter_price_per_m2 refreshed: 52492 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_quarter_price(db: Session, *, concurrently: bool = True) -> int:
    """REFRESH MATERIALIZED VIEW mv_quarter_price_per_m2.

    Args:
        db: SQLAlchemy Session (sync).
        concurrently: When True, uses REFRESH CONCURRENTLY — non-blocking but
            requires the unique index mv_quarter_price_pk to exist (created by
            95_mv_quarter_price.sql) and the MV to be already populated.
            Pass False only for the very first populate or after MV recreation.

    Returns:
        Row count in the MV after refresh (for observability / alerting).

    Raises:
        OperationalError: Re-raised if the error is not the known
            "cannot refresh materialized view concurrently" case.
    """
    try:
        if concurrently:
            db.execute(text("REFRESH MATERIALIZED VIEW CONCURRENTLY mv_quarter_price_per_m2"))
        else:
            db.execute(text("REFRESH MATERIALIZED VIEW mv_quarter_price_per_m2"))
        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 refresh"
            )
            db.rollback()
            db.execute(text("REFRESH MATERIALIZED VIEW mv_quarter_price_per_m2"))
            db.commit()
        else:
            raise

    row = db.execute(text("SELECT COUNT(*) FROM mv_quarter_price_per_m2")).first()
    count = int(row[0]) if row else 0
    logger.info("mv_quarter_price_per_m2 refreshed: %d rows", count)
    return count
