"""Celery task: backfill кэша ПЗЗ-регламента ВСЕХ терзон ЕКБ (эпик #1881).

В отличие от ``zone_regulation_refresh.refresh_zone_regulations`` (ленивый прогрев, beat
~ежемесячно) эта задача — явный одноразовый/ad-hoc backfill, чтобы ``financial_estimate`` (#1881)
фаерил для большинства участков: ``max_far`` резолвится из ``zone_regulation_cache`` без
live-urbanCard в hot-пути. На момент задачи в кэше всего ~33 зоны → задача докэширует остальные.

Идемпотентно: ``backfill_ekb_zone_regulations`` пропускает уже закэшированные зоны (cached skip),
так что повторный запуск дешёв (только WFS-перечисление). Per-zone try/except в сервисе —
сбой одной зоны не валит прогон. ``rate_delay_s`` — вежливость к геопорталу.

Mirror conventions (zone_regulation_refresh.py / backend.md): SessionLocal()+try/finally,
sync (не async), commit per-upsert внутри сервиса.
"""

from __future__ import annotations

import logging

from app.core.db import SessionLocal
from app.services.scrapers.ekb_geoportal_client import EKBGeoportalClient
from app.services.site_finder.zone_regulation import (
    _EKB_CITY_BBOX,
    backfill_ekb_zone_regulations,
)
from app.workers.celery_app import celery_app

logger = logging.getLogger(__name__)


@celery_app.task(name="tasks.backfill_zone_regulations.backfill_zone_regulations")
def backfill_zone_regulations(
    bbox: tuple[float, float, float, float] | None = None,
    limit: int | None = None,
    rate_delay_s: float = 1.0,
) -> dict[str, int]:
    """Backfill ``zone_regulation_cache`` по ВСЕМ терзонам ЕКБ (эпик #1881).

    Args:
        bbox: (minlon, minlat, maxlon, maxlat) EPSG:4326. None → дефолтный bbox ЕКБ.
        limit: максимум уникальных незакэшированных зон к фетчу (None = все). Для smoke-теста.
        rate_delay_s: пауза (сек) между live-fetch'ами зон — вежливость к геопорталу.

    Returns:
        {'enumerated_features', 'unique_zones', 'cached_before', 'fetched', 'upserted', 'failed'}.
    """
    target_bbox = bbox if bbox is not None else _EKB_CITY_BBOX
    client = EKBGeoportalClient()
    db = SessionLocal()
    try:
        result = backfill_ekb_zone_regulations(
            db,
            client=client,
            bbox=target_bbox,
            limit=limit,
            rate_delay_s=rate_delay_s,
        )
        logger.info("backfill_zone_regulations done: %s", result)
        return result
    finally:
        db.close()
