"""dgred CRM REST API client with dry-run mode."""

from __future__ import annotations

import logging
from typing import Any

import httpx

from agent_samochodowy.config import Settings

logger = logging.getLogger(__name__)


class DgredClient:
    """Wrapper around dgred API v1. All calls append ?apiKey=... for auth."""

    def __init__(self, settings: Settings) -> None:
        self.base_url = settings.dgred_base_url.rstrip("/")
        self.api_key = settings.dgred_api_key
        self.dry_run = settings.dry_run
        self._http = httpx.Client(timeout=30)
        self._status_cache: dict[str, int] = {}

    # ------------------------------------------------------------------
    # Low-level HTTP
    # ------------------------------------------------------------------

    def _url(self, path: str) -> str:
        sep = "&" if "?" in path else "?"
        return f"{self.base_url}{path}{sep}apiKey={self.api_key}"

    def _get(self, path: str) -> Any:
        resp = self._http.get(self._url(path))
        resp.raise_for_status()
        return resp.json()

    def _post(self, path: str, payload: dict) -> Any:
        if self.dry_run:
            logger.info("[DRY-RUN] POST %s — %s", path, payload)
            return {"id": "dry-run-id"}
        resp = self._http.post(self._url(path), json=payload)
        resp.raise_for_status()
        body = resp.json()
        # dgred wraps responses: {"status":"ok","data":{...}} — unwrap
        if isinstance(body, dict) and "data" in body:
            return body["data"]
        return body

    def _put(self, path: str, payload: dict) -> Any:
        if self.dry_run:
            logger.info("[DRY-RUN] PUT %s — %s", path, payload)
            return {}
        resp = self._http.put(self._url(path), json=payload)
        resp.raise_for_status()
        body = resp.json()
        if isinstance(body, dict) and "data" in body:
            return body["data"]
        return body

    # ------------------------------------------------------------------
    # Status management
    # ------------------------------------------------------------------

    def ensure_statuses(self, names: list[str]) -> dict[str, int]:
        """Ensure required client statuses exist; return name→id map."""
        if self._status_cache:
            return self._status_cache

        if self.dry_run:
            # In dry-run, assign fake IDs
            self._status_cache = {name: i for i, name in enumerate(names, 1)}
            logger.info("[DRY-RUN] Status map: %s", self._status_cache)
            return self._status_cache

        raw = self._get("/client-statuses")
        existing = raw if isinstance(raw, list) else raw.get("data", [])
        name_to_id: dict[str, int] = {}
        for s in existing:
            name_to_id[s["name"]] = s["id"]

        for name in names:
            if name not in name_to_id:
                result = self._post("/client-statuses/add", {"name": name})
                name_to_id[name] = result.get("id", 0)
                logger.info("Created dgred status: %s (id=%s)", name, name_to_id[name])

        self._status_cache = name_to_id
        return name_to_id

    # ------------------------------------------------------------------
    # Client CRUD
    # ------------------------------------------------------------------

    def create_client(self, data: dict) -> dict:
        """Create a new client. Returns the created client dict."""
        return self._post("/clients", data)

    def update_client(self, client_id: int | str, data: dict) -> dict:
        """Update client fields."""
        return self._put(f"/client/{client_id}", data)

    def set_external_id(self, client_id: int | str, external_id: str) -> dict:
        """Set externalId on a client."""
        return self._put(f"/client/{client_id}", {"externalId": external_id})

    # ------------------------------------------------------------------
    # Notes
    # ------------------------------------------------------------------

    def add_note(self, client_id: int | str, content: str) -> dict:
        """Add a note to a client."""
        return self._post(f"/clients/{client_id}/notes", {
            "content": content,
            "showClientPanel": False,
        })

    # ------------------------------------------------------------------
    # Search
    # ------------------------------------------------------------------

    def find_client_by_external_id(self, external_id: str) -> dict | None:
        """Search for a client by externalId. Returns client dict or None."""
        if self.dry_run:
            logger.info("[DRY-RUN] Search client by externalId=%s", external_id)
            return None
        try:
            results = self._get(f"/clients?externalId={external_id}")
            items = results if isinstance(results, list) else results.get("data", [])
            for item in items:
                if item.get("externalId") == external_id:
                    return item
        except (httpx.HTTPStatusError, IndexError, KeyError):
            pass
        return None

    def close(self) -> None:
        self._http.close()
