"""
提示词系统
实现分层提示词组装，支持 Provider 特定优化和自定义指令
"""

from typing import List, Dict, Optional
from pathlib import Path
from enum import Enum
import os
import platform
from datetime import datetime


# ============================================================================
# 提示词加载便利函数
# ============================================================================

_PROMPTS_DIR = Path(__file__).parent.parent / "assets" / "prompts"


def load_agent_prompt(name: str) -> str:
    """
    加载 Agent 提示词（从 assets/prompts/agents/ 目录）

    Args:
        name: 文件名（如 "build.txt"）

    Returns:
        提示词内容，文件不存在则返回空字符串
    """
    path = _PROMPTS_DIR / "agents" / name
    if path.exists():
        return path.read_text(encoding="utf-8")
    return ""


def load_utility_prompt(name: str) -> str:
    """
    加载工具提示词（从 assets/prompts/utilities/ 目录）

    Args:
        name: 文件名（如 "compaction.txt"）

    Returns:
        提示词内容，文件不存在则返回空字符串
    """
    path = _PROMPTS_DIR / "utilities" / name
    if path.exists():
        return path.read_text(encoding="utf-8")
    return ""


# ============================================================================
# 提示词系统
# ============================================================================

class PromptLayer(str, Enum):
    """提示词层次"""
    AGENT = "agent"  # Agent 专用提示词
    ENVIRONMENT = "environment"  # 环境信息
    CUSTOM = "custom"  # 自定义指令


class PromptPart:
    """提示词部分"""
    def __init__(
        self,
        layer: PromptLayer,
        content: str,
        priority: int = 0,
        cacheable: bool = False,
    ):
        self.layer = layer
        self.content = content
        self.priority = priority
        self.cacheable = cacheable


class SystemPrompt:
    """系统提示词管理器"""

    def __init__(
        self,
        prompts_dir: str = "src/assets/prompts",
    ):
        self.prompts_dir = Path(prompts_dir)

        # 缓存
        self._prompt_cache: Dict[str, str] = {}

    async def build(
        self,
        provider: str,
        model: str,
        agent: str,
        session_id: Optional[str] = None,
        include_environment: bool = True,
        include_custom: bool = True,
    ) -> list:
        """
        构建系统提示词

        Args:
            provider: Provider ID（openai, anthropic, google）
            model: 模型 ID
            agent: Agent 名称
            session_id: 会话 ID（可选）
            include_environment: 是否包含环境信息
            include_custom: 是否包含自定义指令

        Returns:
            Message 列表，role 为 AGENT/ENVIRONMENT/CUSTOM
        """
        parts = []

        # 1. Agent 提示词（支持 provider 特定版本）
        agent_prompt = await self._get_agent_prompt(agent, provider)
        if agent_prompt:
            parts.append(PromptPart(
                layer=PromptLayer.AGENT,
                content=agent_prompt,
                priority=0,
                cacheable=True,
            ))

        # 2. 环境信息
        if include_environment:
            env_info = await self._get_environment_info()
            parts.append(PromptPart(
                layer=PromptLayer.ENVIRONMENT,
                content=env_info,
                priority=1,
                cacheable=False,
            ))

        # 3. 自定义指令
        if include_custom:
            custom_instructions = await self._get_custom_instructions()
            if custom_instructions:
                parts.append(PromptPart(
                    layer=PromptLayer.CUSTOM,
                    content=custom_instructions,
                    priority=2,
                    cacheable=True,
                ))

        # 按优先级排序
        parts.sort(key=lambda p: p.priority)

        # PromptLayer → MessageRole 映射
        from provider import Message, MessageRole
        _LAYER_ROLE_MAP = {
            PromptLayer.AGENT: MessageRole.AGENT,
            PromptLayer.ENVIRONMENT: MessageRole.ENVIRONMENT,
            PromptLayer.CUSTOM: MessageRole.CUSTOM,
        }

        return [
            Message(
                role=_LAYER_ROLE_MAP[p.layer],
                content=p.content,
            )
            for p in parts
        ]

    async def _get_agent_prompt(self, agent: str, provider: str = None) -> Optional[str]:
        """
        获取 Agent 提示词，支持 provider 特定版本

        查找顺序：
        1. {provider}_{agent}.txt (如 openai_build.txt)
        2. {agent}.txt (如 build.txt)

        Args:
            agent: Agent 名称
            provider: Provider 名称（可选）

        Returns:
            提示词内容，不存在则返回 None
        """
        # 候选文件列表（按优先级排序）
        candidates = []

        # 1. provider 特定版本
        if provider:
            candidates.append(f"{provider.lower()}_{agent}.txt")

        # 2. 默认版本
        candidates.append(f"{agent}.txt")

        # 按优先级尝试加载
        for filename in candidates:
            content = await self._load_prompt_file("agents", filename)
            if content:
                return content

        return None

    async def _get_environment_info(self) -> str:
        """获取环境信息"""
        cwd = os.getcwd()
        is_git_repo = Path(cwd, ".git").exists()

        lines = [
            "# Environment Information",
            "",
            f"Working directory: {cwd}",
            f"Is directory a git repo: {'Yes' if is_git_repo else 'No'}",
            f"Platform: {platform.system().lower()}",
            f"OS Version: {platform.platform()}",
            f"Today's date: {datetime.now().strftime('%Y-%m-%d')}",
        ]

        return "\n".join(lines)

    async def _get_custom_instructions(self) -> Optional[str]:
        """获取自定义指令（合并所有来源，直接拼接）"""
        instruction_blocks = []

        # 1. 项目根目录文件（原有逻辑）
        project_files = ["AGENT.md", "CONTEXT.md", "AGENTS.md", "CLAUDE.md"]
        for filename in project_files:
            file_path = Path(filename)
            if file_path.exists():
                try:
                    content = file_path.read_text(encoding="utf-8")
                    if content:
                        instruction_blocks.append(f"# {filename}\n{content}")
                        break
                except:
                    pass

        # 2. 项目级规则目录 .dundun/rules/
        project_rules_dir = Path(".dundun/rules")
        if project_rules_dir.is_dir():
            for md_file in sorted(project_rules_dir.glob("*.md")):
                try:
                    content = md_file.read_text(encoding="utf-8")
                    if content:
                        instruction_blocks.append(f"# {md_file.name}\n{content}")
                except:
                    pass

        # 3. 用户级规则目录 ~/.dundon/rules/
        user_rules_dir = Path.home() / ".dundun" / "rules"
        if user_rules_dir.is_dir():
            for md_file in sorted(user_rules_dir.glob("*.md")):
                try:
                    content = md_file.read_text(encoding="utf-8")
                    if content:
                        instruction_blocks.append(f"# {md_file.name}\n{content}")
                except:
                    pass

        if not instruction_blocks:
            return None

        # 直接拼接文件内容
        return "\n\n".join(instruction_blocks)

    async def _load_prompt_file(self, subdir: str, filename: str) -> Optional[str]:
        """加载提示词文件"""
        cache_key = f"{subdir}/{filename}"
        if cache_key in self._prompt_cache:
            return self._prompt_cache[cache_key]

        search_paths = [
            self.prompts_dir / subdir / filename,
            Path("src/assets/prompts") / subdir / filename,
            Path("assets/prompts") / subdir / filename,
            Path("src/prompts") / subdir / filename,
            Path("prompts") / subdir / filename,
        ]

        for file_path in search_paths:
            if file_path.exists():
                try:
                    content = file_path.read_text(encoding="utf-8")
                    self._prompt_cache[cache_key] = content
                    return content
                except:
                    pass

        return None

    def clear_cache(self):
        """清除缓存"""
        self._prompt_cache.clear()


# 全局实例
_system_prompt = None


def get_system_prompt() -> SystemPrompt:
    """获取全局提示词管理器"""
    global _system_prompt
    if _system_prompt is None:
        _system_prompt = SystemPrompt()
    return _system_prompt
