"""
替换执行模块

封装 SearchReplaceManager 的调用，提供统一的替换结果对象。
支持依赖注入以便于测试。
"""

from dataclasses import dataclass, field
from typing import List, Tuple, Optional, Any, Protocol
from loguru import logger

from autocoder.common.search_replace_patch import SearchReplaceManager, ReplaceResult


# ============================================================================
# 协议定义（用于依赖注入）
# ============================================================================


class ReplacerProtocol(Protocol):
    """替换器协议，用于依赖注入。"""

    def replace_with_fallback(
        self, content: str, search_blocks: List[Tuple[str, str]]
    ) -> ReplaceResult:
        """执行带回退策略的替换。"""
        ...


# ============================================================================
# 结果数据结构
# ============================================================================


@dataclass
class ApplyResult:
    """替换操作的统一结果对象。

    Attributes:
        success: 是否成功应用至少一个块
        new_content: 替换后的内容（失败时为原始内容）
        applied_count: 成功应用的块数量
        total_count: 总块数量
        errors: 错误信息列表
        used_strategy: 使用的策略名称
        tried_strategies: 尝试过的策略列表
        raw_result: 原始 ReplaceResult（用于进一步分析）
    """

    success: bool
    new_content: str
    applied_count: int = 0
    total_count: int = 0
    errors: List[str] = field(default_factory=list)
    used_strategy: Optional[str] = None
    tried_strategies: List[str] = field(default_factory=list)
    raw_result: Optional[ReplaceResult] = None


# ============================================================================
# 替换执行器
# ============================================================================


class ReplaceApplier:
    """替换执行器，封装 SearchReplaceManager 的调用。

    支持依赖注入以便于测试：
        applier = ReplaceApplier(manager=mock_manager)
    """

    def __init__(self, manager: Optional[ReplacerProtocol] = None):
        """初始化替换执行器。

        Args:
            manager: 替换管理器实例，为 None 时自动创建默认实例
        """
        self._manager = manager

    @property
    def manager(self) -> ReplacerProtocol:
        """延迟初始化替换管理器。"""
        if self._manager is None:
            self._manager = SearchReplaceManager()
        return self._manager

    def apply(
        self,
        content: str,
        search_blocks: List[Tuple[str, str]],
    ) -> ApplyResult:
        """执行替换操作。

        使用 SearchReplaceManager 的回退策略执行替换，
        返回统一的 ApplyResult 对象。

        Args:
            content: 原始文件内容
            search_blocks: (search, replace) 元组列表

        Returns:
            ApplyResult 对象，包含替换结果和元数据
        """
        if not search_blocks:
            return ApplyResult(
                success=False,
                new_content=content,
                applied_count=0,
                total_count=0,
                errors=["No search blocks provided"],
            )

        try:
            result = self.manager.replace_with_fallback(content, search_blocks)

            if result.success:
                logger.info(
                    f"Replacement succeeded using {result.metadata.get('used_strategy', 'unknown')} strategy"
                )
                return ApplyResult(
                    success=True,
                    new_content=result.new_content or content,
                    applied_count=result.applied_count,
                    total_count=result.total_count,
                    errors=[],
                    used_strategy=result.metadata.get("used_strategy"),
                    tried_strategies=result.metadata.get("tried_strategies", []),
                    raw_result=result,
                )

            # 替换失败
            logger.warning(f"Replacement failed: {result.message}")
            return ApplyResult(
                success=False,
                new_content=content,
                applied_count=result.applied_count,
                total_count=result.total_count,
                errors=result.errors if result.errors else [result.message],
                used_strategy=result.metadata.get("used_strategy"),
                tried_strategies=result.metadata.get("tried_strategies", []),
                raw_result=result,
            )

        except Exception as e:
            logger.error(f"Error during replacement: {e}")
            return ApplyResult(
                success=False,
                new_content=content,
                applied_count=0,
                total_count=len(search_blocks),
                errors=[f"System error during text replacement: {str(e)}"],
            )


# ============================================================================
# 便捷函数
# ============================================================================


def apply_replacements(
    content: str,
    search_blocks: List[Tuple[str, str]],
    manager: Optional[ReplacerProtocol] = None,
) -> ApplyResult:
    """执行替换操作的便捷函数。

    Args:
        content: 原始文件内容
        search_blocks: (search, replace) 元组列表
        manager: 可选的替换管理器（用于测试注入）

    Returns:
        ApplyResult 对象
    """
    applier = ReplaceApplier(manager=manager)
    return applier.apply(content, search_blocks)


def apply_replacements_simple(
    content: str,
    search_blocks: List[Tuple[str, str]],
    manager: Optional[ReplacerProtocol] = None,
) -> Tuple[bool, str, List[str]]:
    """执行替换操作，返回简化的三元组（兼容旧接口）。

    Args:
        content: 原始文件内容
        search_blocks: (search, replace) 元组列表
        manager: 可选的替换管理器

    Returns:
        (success, new_content, errors) 三元组
    """
    result = apply_replacements(content, search_blocks, manager)
    return result.success, result.new_content, result.errors
