"""CLI: загрузка ГАР-знаменателя «квартир на дом» + матч к houses (мигр. 143/144).

Запуск (каталог — УЖЕ распакованный ГАР региона, напр. папка `66/` из gar_xml.zip):

    python -m app.tasks.gar_flats_load --dir /data/gar/66 --region 66 --version 2026-06-01

Делает два шага в одной транзакционной сессии:
  1. load_gar_region — стриминговый парс XML → UPSERT gar_house_flats (коммит).
  2. match_houses_to_gar — UPDATE houses.gar_flat_count по КАНОНИЧЕСКОМУ адресу (мигр. 144).

Ре-матч без повторного парса многогигабайтного XML (gar_house_flats уже загружена):

    python -m app.tasks.gar_flats_load --match-only --region 66

В режиме `--match-only` шаг парса/загрузки пропускается целиком; `--dir` не требуется.

Многогигабайтный ДАМП качается/распаковывается отдельно (ops-шаг, см.
docs/gar-flats-runbook.md) — этот лоадер потребляет уже распакованные XML локально.
"""

from __future__ import annotations

import argparse
import logging
from datetime import date

from app.core.db import SessionLocal
from app.services.gar_flats_loader import load_gar_region, match_houses_to_gar

logger = logging.getLogger(__name__)

# Город-фильтр матча по умолчанию (см. match_houses_to_gar): ЕКБ-restricted против
# cross-town коллизий в region 66. Пустая строка в --city → None (фильтр отключён).
DEFAULT_CITY_FILTER = "Екатеринбург"


def run_gar_flats_load(
    dir_path: str,
    region_code: str,
    gar_version: str,
    *,
    city_filter: str | None = DEFAULT_CITY_FILTER,
) -> dict[str, int]:
    """Парс+UPSERT (load_gar_region) затем матч (match_houses_to_gar). Возвращает счётчики."""
    db = SessionLocal()
    try:
        load = load_gar_region(dir_path, region_code, gar_version, db=db)
        matched = match_houses_to_gar(db, region_code=region_code, city_filter=city_filter)
        db.commit()
    finally:
        db.close()

    counts = load.to_counts()
    counts["houses_matched"] = matched
    logger.info(
        "gar_flats_load DONE: region=%s version=%s houses=%d apartments=%d upserted=%d "
        "houses_matched=%d duration=%ds",
        region_code,
        gar_version,
        counts["houses"],
        counts["apartments"],
        counts["upserted"],
        matched,
        counts["duration_sec"],
    )
    return counts


def run_gar_match_only(
    region_code: str, *, city_filter: str | None = DEFAULT_CITY_FILTER
) -> dict[str, int]:
    """Только ре-матч уже загруженного gar_house_flats → houses (без парса XML).

    Идемпотентно (match_houses_to_gar — plain UPDATE с IS DISTINCT FROM gate).
    """
    db = SessionLocal()
    try:
        matched = match_houses_to_gar(db, region_code=region_code, city_filter=city_filter)
        db.commit()
    finally:
        db.close()
    logger.info(
        "gar_flats_load --match-only DONE: region=%s city=%s houses_matched=%d",
        region_code,
        city_filter,
        matched,
    )
    return {"houses_matched": matched}


def build_parser() -> argparse.ArgumentParser:
    """Парсер CLI (вынесен для тестируемости флагов без запуска main)."""
    parser = argparse.ArgumentParser(
        description="ГАР loader: квартир на дом → gar_house_flats + match к houses"
    )
    # --dir не required: в режиме --match-only парс пропускается (валидируем в main).
    parser.add_argument("--dir", help="каталог с распакованными ГАР XML региона")
    parser.add_argument("--region", default="66", help="код региона (по умолчанию 66)")
    parser.add_argument(
        "--version",
        default=date.today().isoformat(),
        help="версия ГАР-дампа YYYY-MM-DD (по умолчанию сегодня)",
    )
    parser.add_argument(
        "--match-only",
        action="store_true",
        help="пропустить парс/загрузку ГАР, только пере-матчить gar_house_flats к houses",
    )
    parser.add_argument(
        "--city",
        default=DEFAULT_CITY_FILTER,
        help="город-фильтр матча (ILIKE по full_address); пусто = без ограничения (не-ЕКБ)",
    )
    return parser


def main() -> None:
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s %(levelname)s %(name)s: %(message)s",
    )
    parser = build_parser()
    args = parser.parse_args()

    # Пустой --city → None (фильтр отключён).
    city_filter = args.city or None

    if args.match_only:
        run_gar_match_only(args.region, city_filter=city_filter)
        return

    if not args.dir:
        parser.error("--dir обязателен, кроме режима --match-only")

    run_gar_flats_load(args.dir, args.region, args.version, city_filter=city_filter)


if __name__ == "__main__":
    main()
