"""
Worker de sincronizacion offline → servidor.

Se ejecuta como daemon thread cada SYNC_INTERVAL_S segundos.
Cuando hay ventas pendientes en offline_queue y el servidor esta disponible,
las envia en batch con POST /api/sync/upload.

El servidor debe ser idempotente: si recibe un session_id ya conocido, lo ignora.
"""
import threading
import time

import api
import offline_queue
import session as _session

SYNC_INTERVAL_S = 60   # intentar sync cada 60 segundos


def _build_agent_id() -> str:
    """Construye un agent_id legible con venue + hostname."""
    import socket
    venue = _session.get_venue_id() or api.get_venue_id()
    try:
        host = socket.gethostname()
    except Exception:
        host = "pos"
    return f"{venue}-{host}"


def _try_sync():
    """Intenta sincronizar las ventas pendientes. No lanza excepciones."""
    try:
        pending = offline_queue.get_pending()
        if not pending:
            return

        agent_id = _build_agent_id()
        sales = [
            {
                "session_id":     row["session_id"],
                "package_id":     row["package_id"],
                "package_name":   row["package_name"],
                "payment_method": row["payment_method"],
                "amount":         row["amount"],
                "cashier":        row["cashier"],
                "minutes":        row["minutes"],
                "green_minutes":  row["green_minutes"],
                "blue_minutes":   row["blue_minutes"],
                "red_minutes":    row["red_minutes"],
                "programmed_at":  row["programmed_at"],
                "venue_id":       row["venue_id"],
            }
            for row in pending
        ]

        result = api.sync_upload(agent_id=agent_id, sales=sales)

        if result.get("status") == "ok":
            synced_ids = [r["session_id"] for r in pending]
            offline_queue.mark_synced(synced_ids)
            print(f"[sync_worker] {len(synced_ids)} venta(s) sincronizada(s) con el servidor.")
        # Si falla (servidor sigue caido), no marcamos nada — se reintenta la proxima vez.
    except Exception as e:
        print(f"[sync_worker] Error en sync: {e}")


def _loop():
    """Bucle principal del worker (corre en daemon thread)."""
    while True:
        time.sleep(SYNC_INTERVAL_S)
        _try_sync()


_started = False
_lock = threading.Lock()


def start():
    """Inicia el worker en un daemon thread. Solo lo inicia una vez."""
    global _started
    with _lock:
        if _started:
            return
        _started = True

    t = threading.Thread(target=_loop, daemon=True, name="sync_worker")
    t.start()
    print("[sync_worker] Worker de sync offline iniciado.")
