"""
Client FlareSolverr — interface stateless.

Workflow :
  1. fs = FlareSolverr(url)
  2. session_id = fs.create_session()
  3. fs.get(warmup_url, session_id)      → résout le challenge CF
  4. status, body = fs.get(ajax_url, session_id) → réutilise le même Chrome
  5. fs.destroy_session(session_id)      → libère la ressource Chrome
"""
import logging
from typing import Optional, Tuple

import requests

log = logging.getLogger(__name__)


class FlareSolverrError(Exception):
    pass


class FlareSolverr:
    def __init__(self, base_url: str, timeout_ms: int = 90_000):
        self.base_url = base_url.rstrip("/")
        self.timeout_ms = timeout_ms

    def healthy(self) -> bool:
        try:
            r = requests.get(f"{self.base_url}/health", timeout=5)
            return r.ok
        except Exception:
            return False

    def create_session(self) -> str:
        """Ouvre une session Chrome persistante dans FlareSolverr, retourne le session_id."""
        data = self._call({"cmd": "sessions.create"})
        session_id = data["session"]
        log.info(f"[fs] created session {session_id}")
        return session_id

    def destroy_session(self, session_id: str):
        """Libère la session Chrome."""
        try:
            self._call({"cmd": "sessions.destroy", "session": session_id})
            log.info(f"[fs] destroyed session {session_id}")
        except Exception as e:
            log.warning(f"[fs] destroy session {session_id} failed: {e}")

    def get(self, url: str, session_id: Optional[str] = None) -> Tuple[int, str]:
        """
        GET via FlareSolverr. Retourne (http_status_code, response_body).
        Si session_id fourni, réutilise le Chrome existant (pas de re-warmup).
        """
        payload: dict = {"cmd": "request.get", "url": url, "maxTimeout": self.timeout_ms}
        if session_id:
            payload["session"] = session_id
        data = self._call(payload)
        sol = data.get("solution", {})
        status = sol.get("status", 0)
        body = sol.get("response", "")
        log.debug(f"[fs] GET {url} → {status}")
        return status, body

    def _call(self, payload: dict) -> dict:
        try:
            r = requests.post(
                f"{self.base_url}/v1",
                json=payload,
                timeout=self.timeout_ms / 1000 + 10,
            )
            r.raise_for_status()
            data = r.json()
        except Exception as e:
            raise FlareSolverrError(f"FlareSolverr request failed: {e}") from e
        if data.get("status") != "ok":
            raise FlareSolverrError(f"FlareSolverr error: {data.get('message', data)}")
        return data
