from __future__ import annotations

import logging
import queue
import threading

from app import pipeline, store
from app.cleanup import purge
from app.config import get_settings

log = logging.getLogger("vaani.worker")

_jobs: queue.Queue[str] = queue.Queue()
_stop = threading.Event()
_thread: threading.Thread | None = None
_janitor: threading.Thread | None = None
_ACTIVE = {"queued", "preparing", "audio", "transcript"}


def start() -> None:
    global _thread, _janitor
    _stop.clear()
    _thread = threading.Thread(target=_loop, name="vaani-jobs", daemon=True)
    _thread.start()
    _janitor = threading.Thread(target=_cleanup_loop, name="vaani-cleanup", daemon=True)
    _janitor.start()


def stop() -> None:
    _stop.set()


def submit(job_id: str) -> None:
    _jobs.put(job_id)


def recover() -> None:
    for job in store.list_jobs():
        status = job.get("status")
        if status not in _ACTIVE:
            continue
        job_id = job["id"]

        def mutate(current: dict, status=status) -> None:
            if status != "queued":
                for name in ("preparing", "audio", "transcript"):
                    step = current["steps"][name]
                    if step["state"] == "active":
                        step["state"] = "pending"
                        step["detail"] = "Resumed after a restart."
            current["status"] = "queued"
            current["error"] = None

        store.update(job_id, mutate)
        submit(job_id)
        log.info("resumed job %s", job_id)


def _loop() -> None:
    while not _stop.is_set():
        try:
            job_id = _jobs.get(timeout=0.5)
        except queue.Empty:
            continue
        try:
            pipeline.run(job_id)
        except Exception:
            log.exception("job %s failed outside the pipeline", job_id)
        finally:
            _jobs.task_done()


def _cleanup_loop() -> None:
    while not _stop.wait(3600):
        try:
            removed = purge(get_settings().retention_hours)
            if removed:
                log.info("removed %s expired recording(s)", removed)
        except Exception:
            log.exception("cleanup failed")
