"""Append-only sync log for cross-device replication."""

from __future__ import annotations

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

logger = logging.getLogger(__name__)


class SyncLog:
    """Append-only log for tracking replicated changes."""

    def __init__(self, log_path: str | Path):
        self._path = Path(log_path)
        self._path.parent.mkdir(parents=True, exist_ok=True)
        self._seq = 0
        self._entries: list[dict[str, Any]] = []
        self._load()

    def append(self, operation: str, data: dict[str, Any]) -> int:
        """Append a change entry and return assigned sequence number."""
        self._seq += 1
        entry = {
            "seq": self._seq,
            "op": operation,
            "data": data,
            "timestamp": int(time.time() * 1000),
            "hash": self._compute_hash(operation, data),
        }
        self._entries.append(entry)
        self._persist_entry(entry)
        return self._seq

    def get_since(self, since_seq: int = 0) -> list[dict[str, Any]]:
        return [entry for entry in self._entries if int(entry.get("seq", 0)) > int(since_seq)]

    def get_latest_seq(self) -> int:
        return self._seq

    def verify_integrity(self) -> bool:
        previous_hash = "genesis"
        for entry in self._entries:
            op = str(entry.get("op", ""))
            data = entry.get("data", {}) if isinstance(entry.get("data"), dict) else {}
            expected = hashlib.sha256(
                f"{previous_hash}:{op}:{json.dumps(data, sort_keys=True)}".encode("utf-8")
            ).hexdigest()[:16]
            if str(entry.get("hash", "")) != expected:
                logger.error("Integrity check failed at seq %s", entry.get("seq"))
                return False
            previous_hash = expected
        return True

    def _compute_hash(self, operation: str, data: dict[str, Any]) -> str:
        previous_hash = self._entries[-1]["hash"] if self._entries else "genesis"
        return hashlib.sha256(
            f"{previous_hash}:{operation}:{json.dumps(data, sort_keys=True)}".encode("utf-8")
        ).hexdigest()[:16]

    def _persist_entry(self, entry: dict[str, Any]) -> None:
        with open(self._path, "a", encoding="utf-8") as handle:
            handle.write(json.dumps(entry) + "\n")

    def _load(self) -> None:
        if not self._path.exists():
            return
        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
                self._entries.append(entry)
                self._seq = max(self._seq, int(entry.get("seq", 0)))
