"""Analytics endpoints for the Sverdlovsk dashboard."""

from __future__ import annotations

import re
from typing import Annotated, Any, Literal

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session

from app.core.db import get_db
from app.schemas.complex_buildings import ComplexBuilding
from app.schemas.recommend import RecommendMixInput, RecommendMixOutput
from app.services import analytics_queries as q
from app.services.analytics import velocity_alerts as va

router = APIRouter()

DEV_ID_RE = re.compile(r"^\d+_\d+$")


def _validate_dev(dev_id: str) -> str:
    if not DEV_ID_RE.match(dev_id):
        raise HTTPException(status_code=400, detail="developer_id must match \\d+_\\d+")
    return dev_id


# ---- Sverdlovsk region ------------------------------------------------------


@router.get("/sverdl/market-pulse")
def sverdl_market_pulse(db: Annotated[Session, Depends(get_db)]) -> list[dict[str, Any]]:
    """Monthly series Jan 2025 → present: total square (тыс м²), sold%, avg price."""
    return q.market_pulse(db, region_code=66)


@router.get("/sverdl/quartirography")
def sverdl_quartirography(
    db: Annotated[Session, Depends(get_db)],
    source: Literal["portfolio", "deals"] = "portfolio",
) -> list[dict[str, Any]]:
    """Что строится (portfolio) vs что покупают (deals) по сегментам."""
    return q.quartirography(db, source=source, region_id=66)


@router.get("/sverdl/pipeline")
def sverdl_pipeline(db: Annotated[Session, Depends(get_db)]) -> list[dict[str, Any]]:
    """По году ввода: total / sold% / unsold% / unopened%."""
    return q.pipeline_by_year(db, region_code=66)


@router.get("/sverdl/districts")
def sverdl_districts(db: Annotated[Session, Depends(get_db)]) -> list[dict[str, Any]]:
    """ЕКБ-районы: ЖК-count, flat-count, area, цены."""
    return q.districts(db)


@router.get("/sverdl/yandex-listings")
def sverdl_yandex_listings(db: Annotated[Session, Depends(get_db)]) -> dict[str, Any]:
    """Снимок активных новостроек Яндекс.Недвижимости."""
    return q.yandex_listings(db)


# ---- Developers -------------------------------------------------------------


@router.get("/developers/top")
def developers_top(
    db: Annotated[Session, Depends(get_db)],
    limit: Annotated[int, Query(ge=1, le=50)] = 15,
) -> list[dict[str, Any]]:
    """Топ-девелоперы Свердл по объёму с Δ sold% за всю доступную историю."""
    return q.top_developers(db, region_code=66, limit=limit)


@router.get("/developers/history")
def developers_history(
    db: Annotated[Session, Depends(get_db)],
    ids: Annotated[str, Query(min_length=1)],
) -> list[dict[str, Any]]:
    """Comma-separated developer_ids → time series sold_perc."""
    dev_ids = [_validate_dev(i.strip()) for i in ids.split(",") if i.strip()]
    if not dev_ids:
        raise HTTPException(status_code=400, detail="ids must contain at least one developer_id")
    return q.developer_history(db, developer_ids=dev_ids, region_code=66)


@router.get("/developers/{developer_id}")
def developer_detail(
    db: Annotated[Session, Depends(get_db)],
    developer_id: str,
) -> dict[str, Any]:
    dev = _validate_dev(developer_id)
    result = q.developer_detail(db, developer_id=dev)
    if result is None:
        raise HTTPException(status_code=404, detail="developer not found")
    return result


@router.get("/developers/{developer_id}/portfolio")
def developer_portfolio(
    db: Annotated[Session, Depends(get_db)],
    developer_id: str,
) -> list[dict[str, Any]]:
    dev = _validate_dev(developer_id)
    return q.developer_portfolio(db, developer_id=dev)


# ---- Per-object drill-in (sale_graph / sales_agg / infra / photos) ----------


@router.get("/object/{obj_id}/sale_graph")
def object_sale_graph(
    db: Annotated[Session, Depends(get_db)],
    obj_id: int,
    type_filter: Annotated[str | None, Query(alias="type")] = None,
) -> list[dict[str, Any]]:
    """Time-series продаж per-ЖК. type=apartments|parking, без фильтра — обе серии."""
    return q.object_sale_graph(db, obj_id=obj_id, type_filter=type_filter)


@router.get("/object/{obj_id}/sales_agg")
def object_sales_agg(
    db: Annotated[Session, Depends(get_db)],
    obj_id: int,
) -> list[dict[str, Any]]:
    """3 строки: apartments + nonliv + parking (total / realised / sold%)."""
    return q.object_sales_agg(db, obj_id=obj_id)


@router.get("/object/{obj_id}/infrastructure")
def object_infrastructure(
    db: Annotated[Session, Depends(get_db)],
    obj_id: int,
    category: Annotated[str | None, Query()] = None,
    max_distance: Annotated[int, Query(ge=0, le=10000)] = 5000,
) -> list[dict[str, Any]]:
    """POI вокруг ЖК. Фильтр по category (Спорт/Образование/...) и radius."""
    return q.object_infrastructure(db, obj_id=obj_id, category=category, max_distance=max_distance)


@router.get("/object/{obj_id}/photos")
def object_photos(
    db: Annotated[Session, Depends(get_db)],
    obj_id: int,
    limit: Annotated[int, Query(ge=1, le=500)] = 100,
) -> list[dict[str, Any]]:
    """Фото-метаданные с photo_url, отсортированные по period_dt DESC."""
    return q.object_photos(db, obj_id=obj_id, limit=limit)


@router.get("/object/{obj_id}")
def object_detail(
    db: Annotated[Session, Depends(get_db)],
    obj_id: int,
) -> dict[str, Any]:
    """Базовая инфа объекта из domrf_kn_objects (имя, адрес, координаты, девелопер)."""
    result = q.object_detail(db, obj_id=obj_id)
    if result is None:
        raise HTTPException(status_code=404, detail="object not found")
    return result


@router.get("/object/{obj_id}/full")
def object_full_detail(
    db: Annotated[Session, Depends(get_db)],
    obj_id: int,
) -> dict[str, Any]:
    """Extended object info — все 30+ новых полей (22begh: specs/accessibility/metro/scores)."""
    result = q.object_full_detail(db, obj_id=obj_id)
    if result is None:
        raise HTTPException(status_code=404, detail="object not found")
    return result


@router.get("/object/{obj_id}/quartirography")
def object_quartirography(
    db: Annotated[Session, Depends(get_db)],
    obj_id: int,
) -> list[dict[str, Any]]:
    """Квартирография ЖК: группировка flats по комнатности с count/area/price."""
    return q.object_flats_quartirography(db, obj_id=obj_id)


@router.get("/object/{obj_id}/checks")
def object_checks(
    db: Annotated[Session, Depends(get_db)],
    obj_id: int,
) -> list[dict[str, Any]]:
    """6 проверок «Проверено на наш.дом.рф» (22f)."""
    return q.object_obj_checks(db, obj_id=obj_id)


@router.get("/object/{obj_id}/documents")
def object_documents(
    db: Annotated[Session, Depends(get_db)],
    obj_id: int,
) -> list[dict[str, Any]]:
    """PDF документы из domrf_kn_documents (22i): декларации, разрешения, отчётность."""
    return q.object_documents(db, obj_id=obj_id)


@router.get("/object/{obj_id}/buildings", response_model=list[ComplexBuilding])
def object_buildings(
    db: Annotated[Session, Depends(get_db)],
    obj_id: int,
) -> list[dict[str, Any]]:
    """Список кадастровых зданий ЖК из cad_buildings."""
    return q.complex_buildings(db, obj_id=obj_id)


# ---- Velocity alerts (Issue #17) -------------------------------------------


@router.get("/velocity-alerts")
def velocity_alerts(
    db: Annotated[Session, Depends(get_db)],
    region_code: Annotated[int, Query(ge=1, le=99)] = 66,
    lookback_months: Annotated[int, Query(ge=6, le=24)] = 9,
    min_zscore: Annotated[float, Query(ge=0.5, le=5.0)] = 2.0,
    min_drop_pct: Annotated[float, Query(ge=0.0, le=100.0)] = 30.0,
    limit: Annotated[int, Query(ge=1, le=200)] = 100,
) -> dict[str, Any]:
    """ЖК с statistical-significance провалом темпа продаж vs своя история.

    Источник: domrf_kn_sale_graph (monthly realised). Детерминированная
    z-score детекция: recent 3-mo mean vs trailing prior-period mean.
    Алерт когда z <= -min_zscore И drop_pct <= -min_drop_pct (двойной gate
    снижает false-positive на шумных low-volume ЖК). severity high/medium.
    """
    return va.detect_velocity_anomalies(
        db,
        region_code=region_code,
        lookback_months=lookback_months,
        min_zscore=min_zscore,
        min_drop_pct=min_drop_pct,
        limit=limit,
    )


# ---- PRINZIP-specific -------------------------------------------------------


@router.get("/prinzip/insights")
def prinzip_insights() -> dict[str, Any]:
    """Static recommendations + benchmarks (from PRINZIP_Strategy_Apr27)."""
    return q.prinzip_insights()


@router.get("/prinzip/districts")
def prinzip_districts(db: Annotated[Session, Depends(get_db)]) -> list[dict[str, Any]]:
    return q.prinzip_district_distribution(db, developer_id="6208_0")


@router.get("/prinzip/objects")
def prinzip_objects(db: Annotated[Session, Depends(get_db)]) -> list[dict[str, Any]]:
    """Список 28 ЖК PRINZIP с агрегатами sales_agg + sparkline-данными для UI таблицы."""
    return q.prinzip_objects_with_velocity(db)


# Funnel-эндпойнты (CRM-данные) перенесены в backend/app/api/v1/admin_leads.py:
# /api/v1/admin/leads/funnel/{monthly,by-source,by-object} с X-Admin-Token.


# ---- Recommender (Уровень 1, rule-based) -----------------------------------


@router.post("/recommend/mix", response_model=RecommendMixOutput)
def recommend_mix(
    payload: RecommendMixInput,
    db: Annotated[Session, Depends(get_db)],
) -> dict[str, Any]:
    """Rule-based квартирография для участка в указанном районе ЕКБ.

    На вход — district_name (8 районов ЕКБ), опционально area_total_m2 и
    target_class. На выход — распределение по 5 бакетам комнатности с
    ожидаемыми ценами/площадями/выручкой и список comparable ЖК.
    """
    return q.recommend_mix(
        db,
        district_name=payload.district_name,
        area_total_m2=payload.area_total_m2,
        target_class=payload.target_class,
        months_window=payload.months_window,
        price_factor=payload.price_factor,
        target_months=payload.target_months,
        horizon_months=payload.horizon_months,
        cad_num=payload.cad_num,
    )
