"""
权限系统
实现细粒度的权限控制，支持 allow/deny/ask 三种动作

=== 权限系统核心 ===
- PermissionAction: 权限动作枚举 (ALLOW/DENY/ASK)
- PermissionRule: 权限规则定义
- PermissionRuleset: 权限规则集管理
- PermissionRequest/Response: 权限请求/响应数据结构
- PermissionManager: 权限管理器（核心）
=== 权限系统核心 ===
"""

from dataclasses import dataclass, field
from typing import List, Optional, Dict, Any, Callable, Awaitable
from enum import Enum
import fnmatch
import asyncio
import json
import os
from pathlib import Path

from prompt_toolkit import PromptSession
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.keys import Keys


# === 权限系统核心：权限动作枚举 ===
class PermissionAction(str, Enum):
    """权限动作"""
    ALLOW = "allow"  # 允许
    DENY = "deny"    # 拒绝
    ASK = "ask"      # 询问用户


class PermissionDeniedError(Exception):
    """权限被拒绝错误"""
    def __init__(self, permission: str, pattern: str, message: str = ""):
        self.permission = permission
        self.pattern = pattern
        super().__init__(message or f"Permission denied: {permission} on {pattern}")


# === 权限系统核心：权限规则类 ===
@dataclass
class PermissionRule:
    """权限规则"""
    permission: str  # 权限名称（工具名或特殊权限）
    pattern: str     # 匹配模式（支持通配符 * 和 **）
    action: PermissionAction  # 动作

    def matches(self, permission: str, target: str) -> bool:
        """
        检查是否匹配

        Args:
            permission: 权限名称
            target: 目标（如文件路径、命令等）

        Returns:
            是否匹配
        """
        # 权限名称必须匹配
        if self.permission != permission and self.permission != "*":
            return False

        # 模式匹配
        return self._match_pattern(self.pattern, target)

    def _match_pattern(self, pattern: str, target: str) -> bool:
        """
        模式匹配（支持通配符）

        Examples:
            "*" -> 匹配所有
            "*.py" -> 匹配所有 .py 文件
            "/home/**" -> 匹配 /home 下所有文件
            "git *" -> 匹配所有 git 命令
        """
        # 处理 ** 通配符
        if "**" in pattern:
            pattern = pattern.replace("**", "*")

        return fnmatch.fnmatch(target, pattern)

    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "permission": self.permission,
            "pattern": self.pattern,
            "action": self.action.value,
        }

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "PermissionRule":
        """从字典创建"""
        return cls(
            permission=data["permission"],
            pattern=data["pattern"],
            action=PermissionAction(data["action"]),
        )


# === 权限系统核心：权限规则集 ===
@dataclass
class PermissionRuleset:
    """权限规则集"""
    rules: List[PermissionRule] = field(default_factory=list)

    def evaluate(
        self,
        permission: str,
        target: str
    ) -> PermissionAction:
        """
        评估权限

        Args:
            permission: 权限名称
            target: 目标

        Returns:
            权限动作
        """
        # 从后向前匹配（后面的规则优先级更高）
        for rule in reversed(self.rules):
            if rule.matches(permission, target):
                return rule.action

        # 默认：询问用户
        return PermissionAction.ASK

    def merge(self, other: "PermissionRuleset") -> "PermissionRuleset":
        """
        合并规则集（other 的规则优先级更高）

        Args:
            other: 另一个规则集

        Returns:
            合并后的规则集
        """
        return PermissionRuleset(
            rules=self.rules + other.rules
        )

    def to_dict(self) -> List[Dict[str, Any]]:
        """转换为字典列表"""
        return [rule.to_dict() for rule in self.rules]

    @classmethod
    def from_dict(cls, data: List[Dict[str, Any]]) -> "PermissionRuleset":
        """从字典列表创建"""
        return cls(rules=[PermissionRule.from_dict(r) for r in data])


# === 权限系统核心：权限请求/响应 ===
@dataclass
class PermissionRequest:
    """权限请求"""
    permission: str  # 权限名称（工具名）
    patterns: List[str]  # 目标列表（如文件路径列表）
    session_id: str  # 会话 ID
    metadata: Optional[Dict[str, Any]] = None  # 元数据
    always: Optional[List[str]] = None  # 总是允许的模式
    tool: Optional[Dict[str, str]] = None  # 工具信息（message_id, call_id）


@dataclass
class PermissionResponse:
    """权限响应"""
    approved: bool  # 是否批准
    remember: bool = False  # 是否记住选择
    remember_pattern: Optional[str] = None  # 记住的模式


# === 权限系统核心：权限管理器 ===
class PermissionManager:
    """权限管理器"""

    # 默认授权记录文件名
    DEFAULT_PERMISSIONS_FILE = "permissions.json"

    def __init__(
        self,
        ask_callback: Optional[Callable[[PermissionRequest, str], Awaitable[PermissionResponse]]] = None,
        websocket_handler = None,
        storage_path: Optional[str] = None,
        interaction_manager = None,
    ):
        """
        初始化权限管理器

        Args:
            ask_callback: 询问用户的回调函数，如果为 None 则使用默认的控制台询问
            websocket_handler: WebSocket 处理器（用于发送权限请求事件）
            storage_path: 授权记录存储路径，默认为 .dundun/permissions.json
            interaction_manager: 交互管理器实例（可选，用于发送权限请求）
        """
        # 默认权限规则
        self.default_ruleset = self._build_default_ruleset()

        # 会话权限缓存
        self.session_rulesets: Dict[str, PermissionRuleset] = {}

        # 用户选择缓存（记住的选择）
        self.remembered_choices: Dict[str, PermissionAction] = {}

        # 询问回调
        self.ask_callback = ask_callback

        # WebSocket 处理器
        self.websocket_handler = websocket_handler

        # 交互管理器（显式注入）
        self._interaction_manager = interaction_manager

        # 权限请求等待队列：request_id -> asyncio.Future
        self._pending_requests: Dict[str, asyncio.Future] = {}

        # 授权记录存储路径（使用 data_dir）
        if storage_path:
            self._storage_path = storage_path
        else:
            from core.paths import get_path_manager
            data_dir = get_path_manager().get_data_dir()
            self._storage_path = str(data_dir / self.DEFAULT_PERMISSIONS_FILE)

        # 加载配置文件规则
        self._load_config_rules()

        # 自动加载已保存的授权记录
        self._load_remembered_choices()

    def _load_config_rules(self):
        """从配置文件加载权限规则（可选）"""
        try:
            from .permission_config import PermissionConfigLoader
            config_rules = PermissionConfigLoader.load()
            if config_rules:
                config_permission_rules = PermissionConfigLoader.build_rules(config_rules)
                # 将配置规则添加到默认规则前面（配置优先）
                default_rules = self.default_ruleset.rules
                self.default_ruleset.rules = config_permission_rules + default_rules
        except ImportError:
            # permission_config 模块不存在，跳过
            pass
        except Exception:
            # 配置加载失败，使用默认规则
            pass

    # === 权限系统核心：默认权限规则 ===
    def _build_default_ruleset(self) -> PermissionRuleset:
        """构建默认权限规则"""
        return PermissionRuleset(rules=[
            # 文件读取：允许项目内文件
            PermissionRule("read", "./**", PermissionAction.ALLOW),
            PermissionRule("read", "/tmp/**", PermissionAction.ALLOW),
            PermissionRule("glob", "*", PermissionAction.ALLOW),
            PermissionRule("grep", "*", PermissionAction.ALLOW),

            # 文件写入：询问
            PermissionRule("write", "./**", PermissionAction.ASK),
            PermissionRule("edit", "./**", PermissionAction.ASK),

            # 外部目录：拒绝（除非明确允许）
            PermissionRule("read", "/*", PermissionAction.ASK),
            PermissionRule("write", "/*", PermissionAction.DENY),
            PermissionRule("edit", "/*", PermissionAction.DENY),

            # Bash 命令：询问
            PermissionRule("bash", "*", PermissionAction.ASK),

            # === 只读命令：允许（不需要权限请求） ===
            # 文件查看类
            PermissionRule("bash", "ls*", PermissionAction.ALLOW),
            PermissionRule("bash", "pwd*", PermissionAction.ALLOW),
            PermissionRule("bash", "cat*", PermissionAction.ALLOW),
            PermissionRule("bash", "more*", PermissionAction.ALLOW),
            PermissionRule("bash", "less*", PermissionAction.ALLOW),
            PermissionRule("bash", "head*", PermissionAction.ALLOW),
            PermissionRule("bash", "tail*", PermissionAction.ALLOW),
            PermissionRule("bash", "file*", PermissionAction.ALLOW),
            PermissionRule("bash", "stat*", PermissionAction.ALLOW),
            PermissionRule("bash", "tree*", PermissionAction.ALLOW),
            PermissionRule("bash", "du*", PermissionAction.ALLOW),
            PermissionRule("bash", "wc*", PermissionAction.ALLOW),

            # 搜索查找类
            PermissionRule("bash", "grep*", PermissionAction.ALLOW),
            PermissionRule("bash", "rg*", PermissionAction.ALLOW),
            PermissionRule("bash", "ag*", PermissionAction.ALLOW),
            PermissionRule("bash", "ack*", PermissionAction.ALLOW),
            PermissionRule("bash", "find*", PermissionAction.ALLOW),
            PermissionRule("bash", "fd*", PermissionAction.ALLOW),
            PermissionRule("bash", "locate*", PermissionAction.ALLOW),
            PermissionRule("bash", "which*", PermissionAction.ALLOW),
            PermissionRule("bash", "whereis*", PermissionAction.ALLOW),
            PermissionRule("bash", "type*", PermissionAction.ALLOW),

            # 文本处理类（只读）
            PermissionRule("bash", "sort*", PermissionAction.ALLOW),
            PermissionRule("bash", "uniq*", PermissionAction.ALLOW),
            PermissionRule("bash", "cut*", PermissionAction.ALLOW),
            PermissionRule("bash", "awk*", PermissionAction.ALLOW),
            PermissionRule("bash", "sed*", PermissionAction.ALLOW),
            PermissionRule("bash", "tr*", PermissionAction.ALLOW),
            PermissionRule("bash", "diff*", PermissionAction.ALLOW),
            PermissionRule("bash", "comm*", PermissionAction.ALLOW),
            PermissionRule("bash", "join*", PermissionAction.ALLOW),
            PermissionRule("bash", "paste*", PermissionAction.ALLOW),
            PermissionRule("bash", "column*", PermissionAction.ALLOW),
            PermissionRule("bash", "jq*", PermissionAction.ALLOW),
            PermissionRule("bash", "yq*", PermissionAction.ALLOW),
            PermissionRule("bash", "xargs*", PermissionAction.ALLOW),

            # 系统信息类
            PermissionRule("bash", "ps*", PermissionAction.ALLOW),
            PermissionRule("bash", "top*", PermissionAction.ALLOW),
            PermissionRule("bash", "htop*", PermissionAction.ALLOW),
            PermissionRule("bash", "free*", PermissionAction.ALLOW),
            PermissionRule("bash", "df*", PermissionAction.ALLOW),
            PermissionRule("bash", "uname*", PermissionAction.ALLOW),
            PermissionRule("bash", "uptime*", PermissionAction.ALLOW),
            PermissionRule("bash", "whoami*", PermissionAction.ALLOW),
            PermissionRule("bash", "id*", PermissionAction.ALLOW),
            PermissionRule("bash", "env*", PermissionAction.ALLOW),
            PermissionRule("bash", "printenv*", PermissionAction.ALLOW),
            PermissionRule("bash", "hostname*", PermissionAction.ALLOW),
            # PermissionRule("bash", "date*", PermissionAction.ALLOW),
            PermissionRule("bash", "cal*", PermissionAction.ALLOW),
            PermissionRule("bash", "lsof*", PermissionAction.ALLOW),
            PermissionRule("bash", "netstat*", PermissionAction.ALLOW),
            PermissionRule("bash", "ss*", PermissionAction.ALLOW),
            PermissionRule("bash", "ifconfig*", PermissionAction.ALLOW),
            PermissionRule("bash", "ip*", PermissionAction.ALLOW),

            # 开发工具查看类
            PermissionRule("bash", "echo*", PermissionAction.ALLOW),
            PermissionRule("bash", "printf*", PermissionAction.ALLOW),
            PermissionRule("bash", "test*", PermissionAction.ALLOW),
            PermissionRule("bash", "[*", PermissionAction.ALLOW),
            PermissionRule("bash", "expr*", PermissionAction.ALLOW),
            PermissionRule("bash", "bc*", PermissionAction.ALLOW),
            PermissionRule("bash", "man*", PermissionAction.ALLOW),
            PermissionRule("bash", "info*", PermissionAction.ALLOW),
            PermissionRule("bash", "help*", PermissionAction.ALLOW),

            # 编程语言版本查看
            PermissionRule("bash", "python --version*", PermissionAction.ALLOW),
            PermissionRule("bash", "python3 --version*", PermissionAction.ALLOW),
            PermissionRule("bash", "node --version*", PermissionAction.ALLOW),
            PermissionRule("bash", "npm --version*", PermissionAction.ALLOW),
            PermissionRule("bash", "npm list*", PermissionAction.ALLOW),
            PermissionRule("bash", "npm ls*", PermissionAction.ALLOW),
            PermissionRule("bash", "npm view*", PermissionAction.ALLOW),
            PermissionRule("bash", "pip list*", PermissionAction.ALLOW),
            PermissionRule("bash", "pip show*", PermissionAction.ALLOW),
            PermissionRule("bash", "pip freeze*", PermissionAction.ALLOW),
            PermissionRule("bash", "pip3 list*", PermissionAction.ALLOW),
            PermissionRule("bash", "pip3 show*", PermissionAction.ALLOW),
            PermissionRule("bash", "pip3 freeze*", PermissionAction.ALLOW),
            PermissionRule("bash", "cargo --version*", PermissionAction.ALLOW),
            PermissionRule("bash", "go version*", PermissionAction.ALLOW),
            PermissionRule("bash", "java --version*", PermissionAction.ALLOW),
            PermissionRule("bash", "java -version*", PermissionAction.ALLOW),

            # Git 操作：特殊处理
            PermissionRule("bash", "git status*", PermissionAction.ALLOW),
            PermissionRule("bash", "git diff*", PermissionAction.ALLOW),
            PermissionRule("bash", "git log*", PermissionAction.ALLOW),
            PermissionRule("bash", "git branch*", PermissionAction.ALLOW),
            PermissionRule("bash", "git show*", PermissionAction.ALLOW),
            PermissionRule("bash", "git blame*", PermissionAction.ALLOW),
            PermissionRule("bash", "git shortlog*", PermissionAction.ALLOW),
            PermissionRule("bash", "git describe*", PermissionAction.ALLOW),
            PermissionRule("bash", "git tag*", PermissionAction.ALLOW),
            PermissionRule("bash", "git remote*", PermissionAction.ALLOW),
            PermissionRule("bash", "git stash list*", PermissionAction.ALLOW),
            PermissionRule("bash", "git config --list*", PermissionAction.ALLOW),
            PermissionRule("bash", "git config --get*", PermissionAction.ALLOW),
            PermissionRule("bash", "git rev-parse*", PermissionAction.ALLOW),
            PermissionRule("bash", "git ls-files*", PermissionAction.ALLOW),
            PermissionRule("bash", "git ls-tree*", PermissionAction.ALLOW),
            PermissionRule("bash", "git cat-file*", PermissionAction.ALLOW),
            PermissionRule("bash", "git commit*", PermissionAction.ASK),
            PermissionRule("bash", "git push*", PermissionAction.ASK),
            PermissionRule("bash", "git push --force*", PermissionAction.DENY),

            # 危险命令：拒绝
            PermissionRule("bash", "rm -rf /*", PermissionAction.DENY),
            PermissionRule("bash", "rm -rf /", PermissionAction.DENY),
            PermissionRule("bash", "sudo *", PermissionAction.DENY),
            PermissionRule("bash", "chmod 777 *", PermissionAction.DENY),

            # 网络查询：允许（只读操作）
            PermissionRule("websearch", "*", PermissionAction.ALLOW),
            PermissionRule("webfetch", "*", PermissionAction.ALLOW),
            PermissionRule("codesearch", "*", PermissionAction.ALLOW),

            # Todo 工具：允许
            PermissionRule("todowrite", "*", PermissionAction.ALLOW),
            PermissionRule("todoread", "*", PermissionAction.ALLOW),

            # Skill 工具：允许
            PermissionRule("skill", "*", PermissionAction.ALLOW),

            # Task 工具：允许
            PermissionRule("task", "*", PermissionAction.ALLOW),
        ])

    # === 权限系统核心：权限检查入口 ===
    async def check(
        self,
        request: PermissionRequest,
        agent_ruleset: Optional[PermissionRuleset] = None,
        session_ruleset: Optional[PermissionRuleset] = None,
    ) -> PermissionAction:
        """
        检查权限，返回评估结果

        Args:
            request: 权限请求
            agent_ruleset: Agent 权限规则集
            session_ruleset: Session 权限规则集

        Returns:
            PermissionAction: ALLOW/DENY/ASK

        Raises:
            PermissionDeniedError: 如果缓存中有拒绝记录
        """
        from core.logger import log_permission_check, log_permission_result

        tool_name = request.permission
        pattern = request.patterns[0] if request.patterns else "*"
        args = request.metadata.get("args", {}) if request.metadata else {}

        # 1. read 操作不需要权限验证
        if tool_name == "read":
            return PermissionAction.ALLOW

        # 2. write/edit 只在写入非当前目录时需要验证
        if tool_name in ["write", "edit"]:
            file_path = args.get("file_path", args.get("path", ""))
            if file_path:
                from pathlib import Path
                try:
                    cwd = Path.cwd().resolve()
                    target_path = Path(file_path).resolve()
                    target_path.relative_to(cwd)
                    # 在当前目录下，不需要权限验证
                    return PermissionAction.ALLOW
                except ValueError:
                    pass  # 不在当前目录下，需要权限验证

        # 3. 其他工具不需要权限验证（除了 bash/write/edit）
        if tool_name not in ["bash", "write", "edit"]:
            return PermissionAction.ALLOW

        log_permission_check(
            action="check",
            tool_name=tool_name,
            pattern=pattern,
            session_id=request.session_id,
        )

        # 4. 检查是否在 always 列表中
        if request.always and pattern in request.always:
            log_permission_result(
                action="allow",
                tool_name=tool_name,
                allowed=True,
                pattern=pattern,
            )
            return PermissionAction.ALLOW

        # 5. 检查是否有记住的选择（使用宽泛模式匹配）
        if self._check_remembered_choice(tool_name, pattern):
            log_permission_result(
                action="allow",
                tool_name=tool_name,
                allowed=True,
                pattern=pattern,
                reason="remembered",
            )
            return PermissionAction.ALLOW

        # 6. 合并规则集（优先级：session > agent > default）并评估
        ruleset = self.default_ruleset
        if agent_ruleset:
            ruleset = ruleset.merge(agent_ruleset)
        if session_ruleset:
            ruleset = ruleset.merge(session_ruleset)

        action = ruleset.evaluate(tool_name, pattern)

        log_permission_result(
            action=action.value,
            tool_name=tool_name,
            allowed=(action == PermissionAction.ALLOW),
            pattern=pattern,
        )

        return action

    def _check_remembered_choice(self, permission: str, pattern: str) -> bool:
        """
        检查是否有匹配的已记住选择

        使用 fnmatch 进行宽泛模式匹配，如 "git add*" 可匹配 "git add src/file.py"

        Args:
            permission: 权限类型
            pattern: 目标模式

        Returns:
            True 如果找到允许的缓存，False 如果没有

        Raises:
            PermissionDeniedError: 如果找到拒绝的缓存
        """
        for cache_key, action in self.remembered_choices.items():
            # cache_key 格式: "tool_name:pattern"
            if ":" not in cache_key:
                continue
            cached_tool, cached_pattern = cache_key.split(":", 1)
            if cached_tool == permission:
                # 使用 fnmatch 进行模式匹配
                if fnmatch.fnmatch(pattern, cached_pattern):
                    if action == PermissionAction.DENY:
                        raise PermissionDeniedError(
                            permission,
                            pattern,
                            f"Permission denied (remembered): {permission} on {pattern}"
                        )
                    return True  # 已缓存允许
        return False

    async def _ask_user(
        self,
        request: PermissionRequest,
        pattern: str,
    ) -> PermissionResponse:
        """
        询问用户

        Args:
            request: 权限请求
            pattern: 目标模式

        Returns:
            用户响应
        """
        from core.logger import log_event
        from core.interaction import InteractionType

        log_event("ask_user_start",
            permission=request.permission,
            pattern=pattern,
            has_websocket_handler=bool(self.websocket_handler),
            has_ask_callback=bool(self.ask_callback),
            has_interaction_manager=bool(self._interaction_manager),
        )

        # 优先使用显式注入的 InteractionManager，其次动态获取全局实例
        interaction_manager = self._interaction_manager
        if interaction_manager is None:
            try:
                from core.interaction import get_interaction_manager
                interaction_manager = get_interaction_manager()
            except Exception:
                interaction_manager = None

        if interaction_manager:
            log_event("using_interaction_manager")

            try:
                response = await interaction_manager.request_permission(
                    session_id=request.session_id,
                    permission=request.permission,
                    pattern=pattern,
                    metadata=request.metadata,
                    timeout=None,
                )

                # Convert to PermissionResponse
                return PermissionResponse(
                    approved=response.approved,
                    remember=response.remember,
                    remember_pattern=response.remember_pattern,
                )
            except RuntimeError as e:
                # InteractionManager 没有注册回调，尝试其他方式
                log_event("interaction_manager_not_available", error=str(e))

        # 回退：使用自定义回调
        if self.ask_callback:
            log_event("using_callback_mode")
            return await self.ask_callback(request, pattern)

        # 没有可用的询问方式，默认拒绝
        log_event("no_ask_method_available")
        return PermissionResponse(approved=False, remember=False)

    # === 权限系统核心：处理权限响应 ===
    def handle_permission_response(
        self,
        request_id: str,
        response: PermissionResponse,
    ) -> None:
        """
        处理来自客户端的权限响应

        Args:
            request_id: 请求 ID
            response: 权限响应
        """
        from core.logger import log_event

        log_event("handle_permission_response",
            request_id=request_id,
            approved=response.approved,
            remember=response.remember,
            has_pending_request=request_id in self._pending_requests
        )

        if request_id in self._pending_requests:
            future = self._pending_requests.pop(request_id)
            if not future.done():
                log_event("setting_future_result", request_id=request_id)
                future.set_result(response)
            else:
                log_event("future_already_done", request_id=request_id)
        else:
            log_event("request_id_not_found", request_id=request_id)

    def _build_permission_message(
        self,
        request: PermissionRequest,
        pattern: str,
    ) -> str:
        """构建权限请求消息"""
        lines = []

        # 权限类型
        lines.append(f"权限类型: {request.permission}")

        # 目标
        lines.append(f"目标: {pattern}")

        # 元数据
        if request.metadata:
            lines.append("\n详细信息:")
            for key, value in request.metadata.items():
                # 截断过长的值
                str_value = str(value)
                if len(str_value) > 100:
                    str_value = str_value[:100] + "..."
                lines.append(f"  {key}: {str_value}")

        # 风险提示
        risk = self._get_risk_level(request.permission, pattern)
        if risk:
            lines.append(f"\n⚠️  风险等级: {risk}")

        return "\n".join(lines)

    def _get_risk_level(self, permission: str, pattern: str) -> Optional[str]:
        """获取风险等级"""
        # 高风险操作
        high_risk_patterns = [
            ("bash", "rm "),
            ("bash", "sudo"),
            ("write", "/"),
            ("edit", "/"),
            ("bash", "git push"),
        ]

        for perm, pat in high_risk_patterns:
            if permission == perm and pat in pattern:
                return "高 🔴"

        # 中风险操作
        medium_risk_patterns = [
            ("bash", "git commit"),
            ("write", ""),
            ("edit", ""),
        ]

        for perm, pat in medium_risk_patterns:
            if permission == perm:
                return "中 🟡"

        return None

    def _generate_broad_pattern(self, permission: str, pattern: str) -> str:
        """
        生成宽泛的匹配模式

        对于 bash 命令，提取命令前两个参数作为模式：
        - "git add src/file.py" -> "git add*"
        - "git commit -m xxx" -> "git commit*"
        - "npm install xxx" -> "npm install*"
        - "ls -la" -> "ls*"
        - 复合命令 "git add x && git commit" -> "git add*"（只取第一个命令）

        对于文件操作，授权到文件所在目录：
        - "/etc/hosts" -> "/etc/*"
        - "/home/user/config.json" -> "/home/user/*"

        Args:
            permission: 权限类型（如 "bash", "write", "edit"）
            pattern: 原始模式

        Returns:
            宽泛的匹配模式
        """
        if not pattern:
            return "*"

        # 对于 bash 命令，提取命令前两个参数
        if permission == "bash":
            # 处理复合命令：只取第一个命令（以 && 或 ; 或 | 分隔）
            first_cmd = pattern.split("&&")[0].split(";")[0].split("|")[0].strip()

            parts = first_cmd.split()
            if len(parts) >= 2:
                # 取前两个部分作为模式（如 "git add"）
                return " ".join(parts[:2]) + "*"
            elif len(parts) == 1:
                # 单个命令（如 "ls"）
                return parts[0] + "*"

        # 对于文件操作，授权到文件所在目录
        if permission in ["write", "edit", "read"]:
            # 如果已经包含通配符，保持原样
            if "*" in pattern:
                return pattern
            # 获取目录部分，添加通配符
            import os.path
            dir_path = os.path.dirname(pattern)
            if dir_path:
                return dir_path + "/*"

        # 默认返回原样
        return pattern

    def add_session_rule(
        self,
        session_id: str,
        rule: PermissionRule,
    ):
        """添加会话级权限规则"""
        if session_id not in self.session_rulesets:
            self.session_rulesets[session_id] = PermissionRuleset(rules=[])

        self.session_rulesets[session_id].rules.append(rule)

    def get_session_ruleset(self, session_id: str) -> Optional[PermissionRuleset]:
        """获取会话权限规则集"""
        return self.session_rulesets.get(session_id)

    def clear_remembered_choices(self):
        """清除记住的选择（同时删除持久化文件）"""
        self.remembered_choices.clear()
        # 删除持久化文件
        if os.path.exists(self._storage_path):
            try:
                os.remove(self._storage_path)
            except Exception:
                pass

    def clear_session_rules(self, session_id: str):
        """清除会话权限规则"""
        if session_id in self.session_rulesets:
            del self.session_rulesets[session_id]

    # === 授权记录持久化 ===

    def _save_remembered_choices(self):
        """保存记住的选择到文件"""
        try:
            data = {
                key: action.value
                for key, action in self.remembered_choices.items()
            }
            with open(self._storage_path, "w", encoding="utf-8") as f:
                json.dump(data, f, indent=2, ensure_ascii=False)
        except Exception as e:
            # 保存失败不影响正常流程，仅记录日志
            try:
                from core.logger import log_event
                log_event("permission_save_error", error=str(e))
            except Exception:
                pass

    def _load_remembered_choices(self):
        """从文件加载已保存的授权记录"""
        if not os.path.exists(self._storage_path):
            return

        try:
            with open(self._storage_path, "r", encoding="utf-8") as f:
                data = json.load(f)

            for key, action_str in data.items():
                try:
                    self.remembered_choices[key] = PermissionAction(action_str)
                except ValueError:
                    # 无效的动作值，跳过
                    continue

            # 加载成功后记录日志
            try:
                from core.logger import log_event
                log_event(
                    "permission_loaded",
                    count=len(self.remembered_choices),
                    path=self._storage_path,
                )
            except Exception:
                pass

        except Exception as e:
            # 加载失败不影响正常流程
            try:
                from core.logger import log_event
                log_event("permission_load_error", error=str(e))
            except Exception:
                pass

    def remember_choice(self, permission: str, pattern: str, action: PermissionAction):
        """
        记住用户的授权选择并持久化

        Args:
            permission: 权限名称
            pattern: 目标模式
            action: 权限动作
        """
        cache_key = f"{permission}:{pattern}"
        self.remembered_choices[cache_key] = action
        # 自动保存到文件
        self._save_remembered_choices()


# 全局权限管理器实例
_permission_manager = None


def get_permission_manager() -> PermissionManager:
    """获取全局权限管理器"""
    global _permission_manager
    if _permission_manager is None:
        _permission_manager = PermissionManager()
    return _permission_manager
