"""Service for handling plan merge strategy operations.

This module provides the MergeStrategyService for applying merge strategies
to resolve conflicts during plan merging.
"""

from typing import Any

from .merge_strategy import MergeStrategy


class MergeConflict:
    """Represents a conflict during plan merge.

    Attributes:
        path: The path to the conflicting field
        parent_value: The value from the parent plan
        subplan_value: The value from the subplan
    """

    def __init__(self, path: str, parent_value: Any, subplan_value: Any) -> None:
        """Initialize a merge conflict.

        Args:
            path: The path to the conflicting field
            parent_value: The value from the parent plan
            subplan_value: The value from the subplan
        """
        self.path = path
        self.parent_value = parent_value
        self.subplan_value = subplan_value

    def __eq__(self, other: object) -> bool:
        """Check equality based on all fields."""
        if not isinstance(other, MergeConflict):
            return NotImplemented
        return (
            self.path == other.path
            and self.parent_value == other.parent_value
            and self.subplan_value == other.subplan_value
        )

    def __repr__(self) -> str:
        """Return string representation of the conflict."""
        return (
            f"MergeConflict(path={self.path!r}, "
            f"parent_value={self.parent_value!r}, "
            f"subplan_value={self.subplan_value!r})"
        )


class MergeStrategyService:
    """Service for applying merge strategies to resolve conflicts.

    This service handles the resolution of conflicts that occur during
    three-way merges of parent plans with subplans.
    """

    def __init__(self, strategy: MergeStrategy = MergeStrategy.MANUAL) -> None:
        """Initialize the merge strategy service.

        Args:
            strategy: The merge strategy to use (default: MANUAL)
        """
        self.strategy = strategy

    def resolve_conflicts(self, conflicts: list[MergeConflict]) -> dict[str, Any]:
        """Resolve conflicts using the configured merge strategy.

        Args:
            conflicts: List of conflicts to resolve

        Returns:
            Dictionary mapping conflict paths to resolved values

        Raises:
            ValueError: If strategy is MANUAL and conflicts exist
        """
        if not conflicts:
            return {}

        if self.strategy.is_manual():
            raise ValueError(
                f"Cannot auto-resolve {len(conflicts)} conflicts with "
                f"MANUAL merge strategy. Conflicts must be resolved manually."
            )

        resolved: dict[str, Any] = {}
        for conflict in conflicts:
            if self.strategy == MergeStrategy.PREFER_PARENT:
                resolved[conflict.path] = conflict.parent_value
            elif self.strategy == MergeStrategy.PREFER_SUBPLAN:
                resolved[conflict.path] = conflict.subplan_value

        return resolved

    def has_conflicts(self, conflicts: list[MergeConflict]) -> bool:
        """Check if there are any conflicts.

        Args:
            conflicts: List of conflicts to check

        Returns:
            True if there are conflicts, False otherwise
        """
        return len(conflicts) > 0

    def can_auto_resolve(self) -> bool:
        """Check if the current strategy can auto-resolve conflicts.

        Returns:
            True if the strategy can auto-resolve, False otherwise
        """
        return self.strategy.is_auto_resolve()
