import atexit, sys, threading, time
from dataclasses import dataclass, field
from queue import Queue, Empty
from typing import Optional, Callable

@dataclass
class AnchorJob:
    file_path: str
    file_hash: str
    api_key: Optional[str] = None
    context: Optional[dict] = None
    attempt: int = 0
    max_attempts: int = 3
    created_at: float = field(default_factory=time.time)

class AnchorQueue:
    def __init__(self):
        self._queue = Queue()
        self._running = False
        self._thread = None
        self._lock = threading.Lock()
        self.on_success = None
        self.on_failure = None
    def start(self):
        with self._lock:
            if self._running: return
            self._running = True
            self._thread = threading.Thread(target=self._worker, daemon=True)
            self._thread.start()
            atexit.register(self.shutdown)
    def submit(self, job):
        if not self._running: self.start()
        self._queue.put(job)
    def shutdown(self, timeout=5.0):
        with self._lock:
            if not self._running: return
            self._running = False
        deadline = time.time() + timeout
        while not self._queue.empty() and time.time() < deadline: time.sleep(0.1)
        if self._thread and self._thread.is_alive(): self._thread.join(timeout=1.0)
    @property
    def pending(self): return self._queue.qsize()
    def _worker(self):
        while self._running or not self._queue.empty():
            try: job = self._queue.get(timeout=0.5)
            except Empty: continue
            self._process_job(job)
            self._queue.task_done()
    def _process_job(self, job):
        try:
            from umarise import UmariseCore
            client = UmariseCore(api_key=job.api_key)
            result = client.attest(f"sha256:{job.file_hash}")
            origin_id = getattr(result, "origin_id", None) or "unknown"
            proof_status = getattr(result, "proof_status", None) or "pending"
            print(f"[umarise] ✓ Anchored {job.file_path} → {origin_id}", file=sys.stderr)
            if self.on_success: self.on_success(job, origin_id, proof_status)
        except Exception as e:
            job.attempt += 1
            if job.attempt < job.max_attempts:
                time.sleep(2 ** (job.attempt - 1))
                self._queue.put(job)
            elif self.on_failure: self.on_failure(job, str(e))
