"""
core/permissions.py - Agent 权限管理模块
========================================
管理每个 Agent 的能力权限，包括执行、文件读写、联网、通信等。

权限设计:
  - 每个 agent 有独立的权限配置
  - 权限默认值: execution=True, file_io=True, network=True, local_comm=True, remote_comm=False
  - 权限可通过配置文件 / 运行时 API 动态修改
  - 权限检查嵌入到 executor、file skills、search skills、communication 等模块
  - 支持 per-agent 覆盖（如某些 agent 禁止执行 shell 命令）

权限分类:
  ┌─────────────────┬───────┬──────────────────────────────────┐
  │ 权限项           │ 默认值 │ 说明                             │
  ├─────────────────┼───────┼──────────────────────────────────┤
  │ execution       │ True  │ 代码执行 (shell/ps/cmd/python)   │
  │ file_read       │ True  │ 文件读取                          │
  │ file_write      │ True  │ 文件写入/删除/移动                │
  │ network         │ True  │ 联网 (搜索/HTTP/API)             │
  │ local_comm      │ True  │ 本机 agent 间通信                │
  │ remote_comm     │ False │ 跨电脑 agent 通信 (AICQ relay)   │
  └─────────────────┴───────┴──────────────────────────────────┘
"""
from __future__ import annotations

import json
import logging
from dataclasses import dataclass, field, asdict
from pathlib import Path
from typing import Optional, Dict, List, Any

logger = logging.getLogger("myagent.permissions")


# ==============================================================================
# 权限定义
# ==============================================================================

@dataclass
class AgentPermissions:
    """
    单个 Agent 的权限配置。

    所有权限项均为 bool，默认值反映了安全优先的设计:
    - 跨电脑通信 (remote_comm) 默认关闭
    - 其余功能默认打开（本地桌面助手需要完整能力）
    """
    execution: bool = True       # 代码执行 (shell/powershell/cmd/python)
    file_read: bool = True       # 文件读取
    file_write: bool = True      # 文件写入/删除/移动
    network: bool = True         # 联网 (搜索/HTTP请求/API调用)
    local_comm: bool = True      # 本机 agent 间通信 (LocalChannel)
    remote_comm: bool = False    # 跨电脑 agent 通信 (RemoteChannel/AICQ)

    # 附加约束
    allowed_dirs: List[str] = field(default_factory=list)   # 允许访问的目录 (空=全部)
    blocked_commands: List[str] = field(default_factory=list) # 额外禁用的命令模式

    def to_dict(self) -> dict:
        return asdict(self)

    @classmethod
    def from_dict(cls, data: dict) -> "AgentPermissions":
        """从字典创建权限配置，忽略未知字段"""
        valid_fields = {f.name for f in cls.__dataclass_fields__.values()}
        filtered = {k: v for k, v in data.items() if k in valid_fields}
        return cls(**filtered)

    def check(self, permission: str) -> bool:
        """检查指定权限是否开启"""
        return bool(getattr(self, permission, False))

    def summary(self) -> dict:
        """返回权限摘要（用于状态展示）"""
        labels = {
            "execution": "代码执行",
            "file_read": "文件读取",
            "file_write": "文件写入",
            "network": "联网功能",
            "local_comm": "本机通信",
            "remote_comm": "跨电脑通信",
        }
        return {
            label: getattr(self, key, False)
            for key, label in labels.items()
        }


# ==============================================================================
# 权限管理器
# ==============================================================================

class PermissionManager:
    """
    权限管理器 — 集中管理所有 Agent 的权限配置。

    功能:
      - 维护 per-agent 权限表 (agent_name -> AgentPermissions)
      - 提供默认权限 + per-agent 覆盖
      - 持久化到 JSON 文件
      - 运行时动态修改权限（热更新友好）
      - 权限检查 API (check_permission / require_permission)

    使用方式:
      pm = PermissionManager()
      pm.load()  # 从文件加载

      # 检查权限
      if pm.check_permission("main_agent", "execution"):
          ...

      # 修改权限
      pm.set_permission("main_agent", "execution", False)
      pm.save()
    """

    # 所有已定义的权限项
    ALL_PERMISSIONS = [
        "execution",
        "file_read",
        "file_write",
        "network",
        "local_comm",
        "remote_comm",
    ]

    # 权限中文标签
    PERMISSION_LABELS = {
        "execution": "代码执行",
        "file_read": "文件读取",
        "file_write": "文件写入",
        "network": "联网功能",
        "local_comm": "本机通信",
        "remote_comm": "跨电脑通信",
    }

    def __init__(self, data_dir: str = "", default_permissions: Optional[AgentPermissions] = None):
        """
        Args:
            data_dir: 数据目录，用于存储权限配置文件
            default_permissions: 全局默认权限（未单独配置的 agent 使用此默认值）
        """
        self._data_dir = Path(data_dir) if data_dir else Path.home() / ".myagent" / "data"
        self._permissions_file = self._data_dir / "permissions.json"
        self._default_permissions = default_permissions or AgentPermissions()
        # agent_name -> AgentPermissions
        self._agent_permissions: Dict[str, AgentPermissions] = {}

    # ── 加载 / 保存 ─────────────────────────────────────────────

    def load(self) -> None:
        """从 JSON 文件加载权限配置"""
        if not self._permissions_file.exists():
            # 首次运行，创建默认配置
            self._ensure_dir()
            self.save()
            logger.info(f"权限配置已初始化: {self._permissions_file}")
            return

        try:
            with open(self._permissions_file, "r", encoding="utf-8") as f:
                data = json.load(f)

            # 加载默认权限（如果有）
            if "defaults" in data:
                self._default_permissions = AgentPermissions.from_dict(data["defaults"])

            # 加载 per-agent 权限
            agents = data.get("agents", {})
            for agent_name, perm_data in agents.items():
                self._agent_permissions[agent_name] = AgentPermissions.from_dict(perm_data)

            logger.info(f"权限配置已加载: {len(self._agent_permissions)} 个 agent 自定义权限")

        except (json.JSONDecodeError, IOError) as e:
            logger.warning(f"权限配置加载失败，使用默认值: {e}")
            self._agent_permissions = {}

    def save(self) -> None:
        """保存权限配置到 JSON 文件"""
        self._ensure_dir()

        data = {
            "defaults": self._default_permissions.to_dict(),
            "agents": {
                name: perm.to_dict()
                for name, perm in self._agent_permissions.items()
            },
        }

        with open(self._permissions_file, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)

    def _ensure_dir(self) -> None:
        self._data_dir.mkdir(parents=True, exist_ok=True)

    # ── 权限查询 ────────────────────────────────────────────────

    def get_permissions(self, agent_name: str) -> AgentPermissions:
        """
        获取指定 agent 的权限。

        如果该 agent 没有单独配置，返回全局默认权限的副本。
        """
        if agent_name in self._agent_permissions:
            return self._agent_permissions[agent_name]
        # 返回默认权限（不修改默认值，返回新副本）
        return AgentPermissions.from_dict(self._default_permissions.to_dict())

    def check_permission(self, agent_name: str, permission: str) -> bool:
        """
        检查指定 agent 是否拥有某项权限。

        Args:
            agent_name: Agent 名称
            permission: 权限项名称 (execution/file_read/file_write/network/local_comm/remote_comm)

        Returns:
            True 如果权限开启
        """
        if permission not in self.ALL_PERMISSIONS:
            logger.warning(f"未知权限项: {permission}")
            return False

        perms = self.get_permissions(agent_name)
        return perms.check(permission)

    def require_permission(self, agent_name: str, permission: str) -> bool:
        """
        要求指定权限，权限不足时记录警告。

        Args:
            agent_name: Agent 名称
            permission: 权限项名称

        Returns:
            True 如果权限通过
        """
        if self.check_permission(agent_name, permission):
            return True

        label = self.PERMISSION_LABELS.get(permission, permission)
        logger.warning(f"[权限] Agent '{agent_name}' 没有 '{label}' 权限，操作被拒绝")
        return False

    # ── 权限修改 ────────────────────────────────────────────────

    def set_permission(
        self,
        agent_name: str,
        permission: str,
        value: bool,
    ) -> bool:
        """
        设置指定 agent 的单项权限。

        Args:
            agent_name: Agent 名称
            permission: 权限项名称
            value: True=开启, False=关闭

        Returns:
            True 如果设置成功
        """
        if permission not in self.ALL_PERMISSIONS:
            logger.error(f"未知权限项: {permission}")
            return False

        # 获取或创建该 agent 的权限配置
        if agent_name not in self._agent_permissions:
            # 基于默认权限创建副本
            self._agent_permissions[agent_name] = AgentPermissions.from_dict(
                self._default_permissions.to_dict()
            )

        setattr(self._agent_permissions[agent_name], permission, value)

        label = self.PERMISSION_LABELS.get(permission, permission)
        status = "开启" if value else "关闭"
        logger.info(f"[权限] Agent '{agent_name}' {label} 已{status}")

        return True

    def set_permissions(
        self,
        agent_name: str,
        permissions: Dict[str, bool],
    ) -> bool:
        """
        批量设置指定 agent 的权限。

        Args:
            agent_name: Agent 名称
            permissions: 权限字典 {"execution": True, "network": False, ...}

        Returns:
            True 如果至少有一项被设置
        """
        if not permissions:
            return False

        changed = False
        for perm, value in permissions.items():
            if self.set_permission(agent_name, perm, value):
                changed = True

        return changed

    def set_default_permission(self, permission: str, value: bool) -> bool:
        """
        修改全局默认权限。

        注意: 这只影响没有单独配置的 agent。已单独配置的 agent 不受影响。

        Args:
            permission: 权限项名称
            value: True=开启, False=关闭
        """
        if permission not in self.ALL_PERMISSIONS:
            return False

        setattr(self._default_permissions, permission, value)
        label = self.PERMISSION_LABELS.get(permission, permission)
        status = "开启" if value else "关闭"
        logger.info(f"[权限] 全局默认 {label} 已{status}")
        return True

    def reset_agent_permissions(self, agent_name: str) -> bool:
        """
        重置指定 agent 的权限为全局默认值。

        Returns:
            True 如果该 agent 有自定义配置并被重置
        """
        if agent_name in self._agent_permissions:
            del self._agent_permissions[agent_name]
            logger.info(f"[权限] Agent '{agent_name}' 权限已重置为全局默认")
            return True
        return False

    # ── 状态 / 列表 ─────────────────────────────────────────────

    def get_all_permissions(self) -> Dict[str, dict]:
        """
        获取所有 agent 的权限摘要。

        Returns:
            {"defaults": {...}, "main_agent": {...}, ...}
        """
        result = {
            "_defaults": self._default_permissions.summary(),
        }
        for agent_name, perms in self._agent_permissions.items():
            result[agent_name] = perms.summary()
        return result

    def list_agents(self) -> List[str]:
        """列出所有有自定义权限配置的 agent 名称"""
        return list(self._agent_permissions.keys())

    def get_config_summary(self) -> dict:
        """获取完整的权限配置（用于 Web API / CLI 展示）"""
        return {
            "defaults": self._default_permissions.to_dict(),
            "agents": {
                name: perm.to_dict()
                for name, perm in self._agent_permissions.items()
            },
            "all_permissions": self.ALL_PERMISSIONS,
            "permission_labels": self.PERMISSION_LABELS,
        }
