"""Celery task: refresh mv_layout_velocity (питает «лучшие планировки» best_layouts).

Scheduled via hardcoded beat entry in workers/beat_schedule.py:
  'refresh-layout-velocity' — weekly on Sunday at 03:00 MSK.
  Стоит в «ночном» окне воскресенья, отдельно от monday-кластера тяжёлых
  site_finder-рефрешей (supply-layers / ird / gknspecial / cbr и т.д.), чтобы
  не конкурировать с ними за БД/CPU.

Issue: #1666 (рефреш не был подключён в beat → данные best_layouts молча
устаревали в проде). MV-источник: #113 (PR B, mv_layout_velocity → best_layouts).
"""

from __future__ import annotations

import logging
from typing import Any

from app.core.db import SessionLocal
from app.services.site_finder.layout_velocity_refresh import refresh_layout_velocity
from app.workers.celery_app import celery_app

logger = logging.getLogger(__name__)


@celery_app.task(
    bind=True,
    name="tasks.refresh_layout_velocity.refresh_layout_velocity",
    max_retries=2,
)
def refresh_layout_velocity_task(self: Any) -> dict[str, Any]:
    """REFRESH MATERIALIZED VIEW mv_layout_velocity (best_layouts, #113 / #1666).

    MV рефрешится CONCURRENTLY (non-blocking, требует unique-индекс
    mv_layout_velocity_pk); сервис сам падает в non-concurrent при unpopulated MV.

    Returns result dict for Celery task result store / logging.
    """
    db = SessionLocal()
    try:
        count = refresh_layout_velocity(db, concurrently=True)
        logger.info("refresh_layout_velocity: completed, mv rows=%d", count)
        return {"status": "ok", "mv_layout_velocity_rows": count}
    except Exception as e:
        logger.exception("refresh_layout_velocity failed: %s", e)
        raise
    finally:
        db.close()
