import os
import queue
import threading
from typing import Optional

import httpx

from src.api import tokens_db
from src.utils import logger

_STOP_SENTINEL = object()
_queue: Optional[queue.Queue] = None
_worker_thread: Optional[threading.Thread] = None


def _worker_loop(q: queue.Queue, db_path: str) -> None:
    while True:
        item = q.get()
        try:
            if item is _STOP_SENTINEL:
                return
            kind, payload = item
            if kind == "counter":
                token_id = payload
                try:
                    tokens_db.increment_usage(db_path, token_id)
                except Exception:  # noqa: BLE001
                    logger.warning(
                        "tracking: échec increment_usage token_id=%s",
                        token_id,
                        exc_info=True,
                    )
            elif kind == "matomo":
                try:
                    _post_matomo(**payload)
                except Exception:  # noqa: BLE001
                    logger.warning("tracking: échec envoi Matomo", exc_info=True)
        finally:
            q.task_done()


def _post_matomo(url: str, params: dict) -> None:
    """POST fire-and-forget vers la Tracking API Matomo. Mockable en test."""
    httpx.post(url, data=params, timeout=5.0)


def enqueue_matomo_event(
    token_id: int,
    path: str,
    query_string: str,
    status_code: int,
    user_agent: str,
) -> None:
    if _queue is None:
        return
    if os.getenv("MATOMO_TRACKING_ENABLED", "false").lower() != "true":
        return
    url = os.getenv("MATOMO_URL")
    site_id = os.getenv("MATOMO_SITE_ID")
    if not url or not site_id:
        return
    full_url = f"https://colibre.fr{path}"
    if query_string:
        full_url += f"?{query_string}"
    params = {
        "idsite": site_id,
        "rec": "1",
        "url": full_url,
        "action_name": f"API {path}",
        "uid": f"token-{token_id}",
        "dimension1": str(token_id),
        "dimension2": str(status_code),
        "ua": user_agent,
    }
    _queue.put(("matomo", {"url": url, "params": params}))


def start_worker(db_path: str) -> None:
    global _queue, _worker_thread
    if _worker_thread is not None and _worker_thread.is_alive():
        return
    _queue = queue.Queue()
    _worker_thread = threading.Thread(
        target=_worker_loop, args=(_queue, db_path), daemon=True
    )
    _worker_thread.start()


def stop_worker() -> None:
    global _worker_thread, _queue
    if _worker_thread is None:
        return
    _queue.put(_STOP_SENTINEL)
    _worker_thread.join(timeout=2.0)
    _worker_thread = None
    _queue = None


def enqueue_counter_update(token_id: int) -> None:
    if _queue is None:
        return  # tracking désactivé (tests par ex.)
    _queue.put(("counter", token_id))


def flush(timeout: float = 2.0) -> None:
    """Attend que la queue soit drainée. Utile en test."""
    q = _queue
    if q is None:
        return
    q.join()
