"""Sync conflict resolution strategies for peer replication."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any


class SyncStrategy(ABC):
    """Base class for conflict resolution in sync apply operations."""

    @abstractmethod
    def resolve_memory_conflict(self, local: dict[str, Any], remote: dict[str, Any]) -> dict[str, Any]:
        """Resolve memory conflict between local and remote states."""

    @abstractmethod
    def resolve_entity_conflict(self, local: dict[str, Any], remote: dict[str, Any]) -> dict[str, Any]:
        """Resolve entity conflict between local and remote states."""


class NewerWinsStrategy(SyncStrategy):
    """Most recently updated object wins."""

    def resolve_memory_conflict(self, local: dict[str, Any], remote: dict[str, Any]) -> dict[str, Any]:
        local_ts = int(local.get("updated_at", local.get("created_at", 0)))
        remote_ts = int(remote.get("updated_at", remote.get("created_at", 0)))
        winner = dict(remote if remote_ts > local_ts else local)
        winner["_conflict_resolved"] = True
        winner["_resolution"] = "newer-wins"
        return winner

    def resolve_entity_conflict(self, local: dict[str, Any], remote: dict[str, Any]) -> dict[str, Any]:
        local_ts = int(local.get("last_seen", local.get("last_seen_at", 0)))
        remote_ts = int(remote.get("last_seen", remote.get("last_seen_at", 0)))
        if remote_ts > local_ts:
            merged = dict(remote)
            merged["mention_count"] = max(int(local.get("mention_count", 0)), int(remote.get("mention_count", 0)))
            merged["_conflict_resolved"] = True
            merged["_resolution"] = "newer-wins"
            return merged
        merged = dict(local)
        merged["mention_count"] = max(int(local.get("mention_count", 0)), int(remote.get("mention_count", 0)))
        merged["_conflict_resolved"] = True
        merged["_resolution"] = "newer-wins"
        return merged


class ManualStrategy(SyncStrategy):
    """Flag conflicts for manual resolution."""

    def resolve_memory_conflict(self, local: dict[str, Any], remote: dict[str, Any]) -> dict[str, Any]:
        return {"_conflict": True, "local": local, "remote": remote, "resolution": None}

    def resolve_entity_conflict(self, local: dict[str, Any], remote: dict[str, Any]) -> dict[str, Any]:
        return {"_conflict": True, "local": local, "remote": remote, "resolution": None}


class SemanticMergeStrategy(SyncStrategy):
    """Use local LLM to semantically merge memory content where possible."""

    def __init__(self, llm_client=None):
        from neurovault.cognitive.llm_client import OllamaClient

        self._llm = llm_client or OllamaClient()

    def resolve_memory_conflict(self, local: dict[str, Any], remote: dict[str, Any]) -> dict[str, Any]:
        if not self._llm.is_available():
            return NewerWinsStrategy().resolve_memory_conflict(local, remote)

        merged = self._llm.generate(
            prompt=(
                "Merge these two versions of the same memory:\n"
                f"Version A: {str(local.get('content', ''))[:300]}\n"
                f"Version B: {str(remote.get('content', ''))[:300]}\n"
                "Return one merged version."
            ),
            temperature=0.2,
            max_tokens=512,
        )

        if merged and len(merged.strip()) > 20:
            out = dict(remote)
            out["content"] = merged.strip()
            out["_conflict_resolved"] = True
            out["_resolution"] = "semantic-merge"
            return out

        return NewerWinsStrategy().resolve_memory_conflict(local, remote)

    def resolve_entity_conflict(self, local: dict[str, Any], remote: dict[str, Any]) -> dict[str, Any]:
        return NewerWinsStrategy().resolve_entity_conflict(local, remote)
