"""本地 Artifact 构建器

从本地 problems/<problem>/sandbox/ 目录构建 artifact，
替代从云端下载 artifact。
"""

from __future__ import annotations

import os
from pathlib import Path
from typing import Any

from ..models import PhaseConfig


class LocalArtifactBuilder:
    """本地 Artifact 构建器

    将 problems/<problem>/sandbox/ 目录打包为 artifact_files 字典，
    供 DualSandboxEvaluator 使用。
    """

    # 默认入口点路径
    DEFAULT_ENTRYPOINT = "sandbox/run.py"

    def build(self, problem_path: str | Path, config: PhaseConfig | None = None) -> dict[str, bytes]:
        """构建 artifact

        Args:
            problem_path: 问题目录路径，如 "problems/interrupt_judge"
            config: 可选的 PhaseConfig，用于获取 artifact_entry

        Returns:
            文件名到内容的字典，如 {"sandbox/run.py": b"...", ...}

        Raises:
            FileNotFoundError: 如果 sandbox 目录不存在
        """
        problem_path = Path(problem_path).resolve()
        sandbox_path = problem_path / "sandbox"

        if not sandbox_path.exists():
            raise FileNotFoundError(f"Sandbox directory not found: {sandbox_path}")

        artifact_files: dict[str, bytes] = {}

        # 递归读取 sandbox 目录下的所有文件
        for root, _, files in os.walk(sandbox_path):
            for filename in files:
                file_path = Path(root) / filename

                # 跳过 __pycache__ 和 .pyc 文件
                if "__pycache__" in str(file_path) or file_path.suffix == ".pyc":
                    continue

                # 计算相对路径（相对于 sandbox 目录）
                rel_path = file_path.relative_to(sandbox_path)
                artifact_key = f"sandbox/{rel_path}"

                try:
                    with open(file_path, "rb") as f:
                        artifact_files[artifact_key] = f.read()
                except Exception as e:
                    raise IOError(f"Failed to read {file_path}: {e}")

        # 检查入口点是否存在
        entrypoint = self._resolve_entrypoint(config)
        if entrypoint not in artifact_files:
            raise FileNotFoundError(
                f"Entrypoint not found: {entrypoint}. "
                f"Available files: {list(artifact_files.keys())[:10]}..."
            )

        return artifact_files

    def _resolve_entrypoint(self, config: PhaseConfig | None = None) -> str:
        """解析入口点路径

        优先级：
        1. config.artifact_entry（如果指定）
        2. DEFAULT_ENTRYPOINT
        """
        if config is not None:
            entry = getattr(config, "artifact_entry", None)
            if entry:
                return entry

        return self.DEFAULT_ENTRYPOINT

    def get_user_adapter(self, artifact_files: dict[str, bytes]) -> bytes | None:
        """获取 user_adapter.py 内容

        Args:
            artifact_files: artifact 文件字典

        Returns:
            user_adapter.py 的内容，如果不存在则返回 None
        """
        # 尝试多种可能的路径
        possible_paths = [
            "sandbox/user_adapter.py",
            "user_adapter.py",
        ]

        for path in possible_paths:
            if path in artifact_files:
                return artifact_files[path]

        return None
