"""Wrapper na API CRM dgred.com."""

import logging
import time
from typing import Any, Iterable

import requests

from . import config

log = logging.getLogger(__name__)


class CRMError(Exception):
    """Błąd komunikacji z CRM."""


class CRMClient:
    def __init__(
        self,
        base_url: str = config.CRM_BASE_URL,
        api_key: str = config.CRM_API_KEY,
        timeout: int = config.REQUEST_TIMEOUT,
    ):
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key
        self.timeout = timeout
        self.session = requests.Session()
        self.session.headers.update({"Accept": "application/json"})

    # ---------- niski poziom ----------
    def _url(self, path: str) -> str:
        return f"{self.base_url}{path}"

    def _request(self, method: str, path: str, **kwargs) -> dict:
        params = kwargs.pop("params", {}) or {}
        params["apiKey"] = self.api_key
        try:
            r = self.session.request(
                method, self._url(path), params=params, timeout=self.timeout, **kwargs
            )
        except requests.RequestException as e:
            raise CRMError(f"Network error: {e}") from e

        if r.status_code >= 400:
            raise CRMError(f"{method} {path} → HTTP {r.status_code}: {r.text[:300]}")

        try:
            return r.json()
        except ValueError as e:
            raise CRMError(f"Invalid JSON from {path}: {e}") from e

    # ---------- publiczne API ----------
    def ping(self) -> bool:
        """Test połączenia — zwraca True jeśli API działa."""
        data = self._request("GET", "/clients", params={"limit": 1})
        return data.get("status") == "ok"

    def add_lead(self, data: dict) -> dict:
        """POST /clients — dodanie nowego leada."""
        return self._request("POST", "/clients", json=data)

    def get_all_leads(self, page_size: int = 100) -> list[dict]:
        """GET /clients — paginowane pobranie wszystkich leadów."""
        all_leads: list[dict] = []
        page = 1
        while True:
            resp = self._request(
                "GET", "/clients", params={"page": page, "limit": page_size}
            )
            data = resp.get("data", []) or []
            all_leads.extend(data)
            pages = resp.get("pages", 1)
            if page >= pages or not data:
                break
            page += 1
            time.sleep(0.2)
        return all_leads

    def lead_exists(self, email: str | None, phone: str | None) -> bool:
        """Sprawdzenie czy lead z danym emailem lub telefonem już istnieje.

        Uwaga: do masowej deduplikacji używaj klasy Deduplicator (cache w pamięci).
        Ta metoda wykonuje pełen pull każdorazowo i jest tylko do testów ad-hoc.
        """
        if not email and not phone:
            return False
        leads = self.get_all_leads()
        for lead in leads:
            if email and lead.get("email") and lead["email"].lower() == email.lower():
                return True
            if phone and lead.get("phone") and _norm_phone(lead["phone"]) == _norm_phone(phone):
                return True
        return False

    def add_note(self, client_id: int, note: str) -> dict:
        """POST /clients/{id}/notes."""
        return self._request(
            "POST", f"/clients/{client_id}/notes", json={"content": note}
        )

    def update_lead(self, client_id: int, data: dict) -> dict:
        """PUT /client/{id}."""
        return self._request("PUT", f"/client/{client_id}", json=data)


def _norm_phone(phone: str) -> str:
    return "".join(c for c in (phone or "") if c.isdigit())
