"""Offline-first queue for deferred sync operations."""

from __future__ import annotations

import json
import logging
import time
from pathlib import Path
from typing import Any

logger = logging.getLogger(__name__)


class OfflineQueue:
    """Persist sync operations when peer links are unavailable."""

    def __init__(self, queue_path: str | Path):
        self._path = Path(queue_path)
        self._path.parent.mkdir(parents=True, exist_ok=True)

    def enqueue(self, peer_id: str, operation: str, data: dict[str, Any]) -> None:
        entry = {
            "peer_id": peer_id,
            "operation": operation,
            "data": data,
            "timestamp": int(time.time() * 1000),
            "retries": 0,
        }
        with open(self._path, "a", encoding="utf-8") as handle:
            handle.write(json.dumps(entry) + "\n")

    def dequeue(self, peer_id: str | None = None) -> list[dict[str, Any]]:
        if not self._path.exists():
            return []

        selected: list[dict[str, Any]] = []
        remaining: list[dict[str, Any]] = []

        with open(self._path, encoding="utf-8") as handle:
            for line in handle:
                line = line.strip()
                if not line:
                    continue
                try:
                    entry = json.loads(line)
                except Exception:
                    continue
                if not isinstance(entry, dict):
                    continue

                if peer_id is None or str(entry.get("peer_id", "")) == peer_id:
                    selected.append(entry)
                else:
                    remaining.append(entry)

        with open(self._path, "w", encoding="utf-8") as handle:
            for entry in remaining:
                handle.write(json.dumps(entry) + "\n")

        return selected

    def retry_failed(self, entry: dict[str, Any]) -> None:
        retries = int(entry.get("retries", 0)) + 1
        entry["retries"] = retries
        if retries < 5:
            self.enqueue(str(entry.get("peer_id", "")), str(entry.get("operation", "")), entry.get("data", {}))
            return

        logger.warning(
            "Dropping sync operation after 5 retries: %s -> %s",
            entry.get("operation", "unknown"),
            entry.get("peer_id", "unknown"),
        )

    @property
    def pending_count(self) -> int:
        if not self._path.exists():
            return 0
        with open(self._path, encoding="utf-8") as handle:
            return sum(1 for _ in handle)
