"""HTTP debounce wrapper for triggering the Mailu Keycloak sync job."""

import http.server
import json
import os
import subprocess
import threading

from time import time

# Simple debounce to avoid hammering on bursts
MIN_INTERVAL_SECONDS = 10
WAIT_TIMEOUT_SECONDS = float(os.environ.get("MAILU_SYNC_WAIT_TIMEOUT_SEC", "20"))
last_run = 0.0
lock = threading.Lock()
sync_done = threading.Event()
sync_done.set()
sync_running = False
last_rc = None


def _run_sync_blocking() -> int:
    global last_run, sync_running, last_rc
    with lock:
        if sync_running:
            return 0
        sync_running = True
        sync_done.clear()

    try:
        print("mailu-sync-listener: starting sync", flush=True)
        proc = subprocess.run(["python", "/app/sync.py"], check=False)
        rc = int(proc.returncode)
        print(f"mailu-sync-listener: sync completed rc={rc}", flush=True)
        last_rc = rc
        return rc
    finally:
        with lock:
            sync_running = False
            last_run = time()
            sync_done.set()


def _trigger_sync_async(force: bool = False) -> bool:
    with lock:
        now = time()
        if sync_running:
            return False
        if not force and now - last_run < MIN_INTERVAL_SECONDS:
            return False

    thread = threading.Thread(target=_run_sync_blocking, daemon=True)
    thread.start()
    return True


class Handler(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get("Content-Length", 0))
        body = self.rfile.read(length) if length else b""
        try:
            payload = json.loads(body or b"{}")
        except json.JSONDecodeError:
            self.send_response(400)
            self.end_headers()
            return

        wait = False
        force = False
        if isinstance(payload, dict):
            wait = bool(payload.get("wait"))
            force = bool(payload.get("force"))

        if wait:
            with lock:
                already_running = sync_running

            if not already_running:
                _trigger_sync_async(force=force)

            sync_done.wait(timeout=WAIT_TIMEOUT_SECONDS)
            with lock:
                still_running = sync_running
                rc = last_rc

            if still_running:
                # Avoid blocking callers while a sync is in flight.
                self.send_response(200)
            else:
                self.send_response(200 if rc == 0 else 500)
            self.end_headers()
            return

        _trigger_sync_async(force=force)
        self.send_response(202)
        self.end_headers()

    def log_message(self, fmt, *args):
        # Quiet logging
        return


if __name__ == "__main__":
    server = http.server.ThreadingHTTPServer(("", 8080), Handler)
    server.serve_forever()
