"""
senzib.integrations.amocrm.private_api

Обёртки над приватными AJAX-эндпоинтами amoCRM.

⚠️ Важно:
amoCRM не гарантирует стабильность приватных эндпоинтов
(/ajax/leads/list/ и т.п.). Используйте это на свой риск и
желательно держите под feature-флагами.

Сейчас модуль даёт один основной хелпер:

    get_leads_count_private_with_token(domain, access_token, pipeline_status_map)

который считает количество сделок по воронкам/стадиям через
GET https://{domain}/ajax/leads/list/?only_count=Y&useFilter=y&...

Он:
- Возвращает int (count) или None при любой ошибке / нестандартном ответе.
- НЕ поднимает исключения наружу (безопасно для фоновых задач).
"""

from __future__ import annotations

from typing import Dict, Iterable, List, Optional, Tuple

import requests

from senzib.integrations.amocrm.utils import build_filter_params


def get_leads_count_private_with_token(
    domain: str,
    access_token: str,
    pipeline_status_map: Dict[int, Iterable[int]],
    *,
    timeout: int = 30,
) -> Optional[int]:
    """
    Возвращает количество сделок в аккаунте amoCRM, используя
    приватный AJAX-эндпоинт:

        GET https://{domain}/ajax/leads/list/
            ?only_count=Y
            &useFilter=y
            &filter[pipe][<pipeId>][]=<statusId>
            ...

    Авторизация:
        Authorization: Bearer <access_token>

    :param domain: example.amocrm.ru
    :param access_token: OAuth2 Bearer токен (интеграция/виджет)
    :param pipeline_status_map:
        карта {pipeline_id: [status_id, ...]}, например:
            {
                123: [456, 789],
                321: [654],
            }
        Удобно получить из:
            senzib.integrations.amocrm.utils.build_pipeline_status_map(...)
    :param timeout: таймаут HTTP-запроса (сек)
    :return:
        int (count) или None:
        - при любой сетевой ошибке
        - при статусах != 200
        - при странном формате ответа
    """
    base_url = f"https://{domain}/ajax/leads/list/"

    # Параметры: сначала базовые флаги, затем фильтр по воронкам/стадиям
    params: List[Tuple[str, str]] = [
        ("only_count", "Y"),
        ("useFilter", "y"),
    ] + build_filter_params(pipeline_status_map)

    headers = {
        "Accept": "application/json, text/javascript, */*; q=0.01",
        "X-Requested-With": "XMLHttpRequest",
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json",
    }

    try:
        resp = requests.get(base_url, params=params, headers=headers, timeout=timeout)
    except requests.RequestException:
        # Сетевые ошибки гасим: внешнему коду важно просто знать,
        # что оценка недоступна, но сам процесс не ломаем.
        return None

    if resp.status_code != 200:
        # 204 — нет данных; 401/403 — нет доступа; 500 и т.п. —
        # во всех этих случаях возвращаем None.
        return None

    try:
        data = resp.json() or {}
    except ValueError:
        return None

    cnt = data.get("count")
    try:
        return int(cnt) if cnt is not None else None
    except Exception:
        return None


__all__ = [
    "get_leads_count_private_with_token",
]
