# 中文注释：
# 文件：echobot/utils/instance.py
# 说明：通用工具函数。

"""实例管理工具 - 支持多网关实例隔离架构

此模块提供实例管理功能，允许创建和管理多个完全隔离的 echobot 实例。
每个实例拥有独立的配置、会话、工作区和定时任务。

使用示例:
    from echobot.utils.instance import ensure_instance_structure, list_instances

    # 创建新实例
    instance_dir = ensure_instance_structure("admin")

    # 列出所有实例
    instances = list_instances()
"""

import json
import re
import shutil
from datetime import datetime
from pathlib import Path
from typing import Any


def get_instance_dir(instance_name: str) -> Path:
    """
    获取实例目录路径。

    返回指定实例的完整目录路径，路径格式为：
    ~/.echobot/instances/{instance_name}

    注意：此函数只返回路径，不创建目录。如需创建目录结构，
    请使用 ensure_instance_structure()。

    参数:
        instance_name: 实例名称，如 "admin", "coder"

    返回:
        Path: 实例目录的完整路径

    示例:
        >>> get_instance_dir("admin")
        PosixPath('/home/user/.echobot/instances/admin')
    """
    return Path.home() / ".echobot" / "instances" / instance_name


def validate_instance_name(name: str) -> bool:
    """
    验证实例名称的合法性。

    实例名称只能包含以下字符：
    - 字母 (a-z, A-Z)
    - 数字 (0-9)
    - 下划线 (_)
    - 连字符 (-)

    这是为了确保实例名称可以作为有效的目录名和配置键。

    参数:
        name: 要验证的实例名称

    返回:
        bool: 如果名称合法返回 True，否则返回 False

    示例:
        >>> validate_instance_name("admin-gateway")
        True
        >>> validate_instance_name("admin/gateway")
        False
    """
    if not name:
        return False
    return bool(re.match(r"^[a-zA-Z0-9_-]+$", name))


def instance_exists(instance_name: str) -> bool:
    """
    检查指定实例是否存在。

    通过检查实例目录是否存在来判断实例是否存在。

    参数:
        instance_name: 实例名称

    返回:
        bool: 如果实例存在返回 True，否则返回 False

    示例:
        >>> instance_exists("admin")
        True
        >>> instance_exists("nonexistent")
        False
    """
    return get_instance_dir(instance_name).is_dir()


def ensure_instance_structure(instance_name: str) -> Path:
    """
    确保实例目录结构存在，不存在则创建。

    创建完整的实例目录结构，包括：
    - config.json: 实例配置文件（如不存在则创建默认配置）
    - sessions/: 会话存储目录
    - workspace/: 工作区目录
    - cron/: 定时任务目录

    参数:
        instance_name: 实例名称

    返回:
        Path: 实例目录的路径

    异常:
        ValueError: 如果实例名称不合法

    示例:
        >>> ensure_instance_structure("admin")
        PosixPath('/home/user/.echobot/instances/admin')
        # 同时创建了子目录和默认配置
    """
    # 首先验证实例名称的合法性
    if not validate_instance_name(instance_name):
        raise ValueError(
            f"Invalid instance name: '{instance_name}'. "
            "Instance names can only contain letters, numbers, underscores, and hyphens."
        )

    # 获取实例目录路径
    instance_dir = get_instance_dir(instance_name)

    # 创建主目录
    instance_dir.mkdir(parents=True, exist_ok=True)

    # 创建子目录
    (instance_dir / "sessions").mkdir(exist_ok=True)
    (instance_dir / "workspace").mkdir(exist_ok=True)
    (instance_dir / "cron").mkdir(exist_ok=True)

    # 创建默认配置文件（如果不存在）
    config_path = instance_dir / "config.json"
    if not config_path.exists():
        default_config = {
            "agents": {
                "defaults": {
                    "workspace": f"~/.echobot/instances/{instance_name}/workspace",
                    "model": "anthropic/claude-opus-4-5",
                    "maxTokens": 8192,
                    "temperature": 0.7,
                    "maxToolIterations": 20,
                    "default_role": None,
                }
            },
            "providers": {},
            "channels": {},
            "tools": {"web": {"search": {}}},
        }
        with open(config_path, "w", encoding="utf-8") as f:
            json.dump(default_config, f, indent=2, ensure_ascii=False)

    return instance_dir


def list_instances() -> list[dict[str, Any]]:
    """
    列出所有已创建的实例。

    扫描 ~/.echobot/instances/ 目录，返回所有实例的信息。

    返回:
        list[dict]: 实例信息列表，每个字典包含：
            - name: 实例名称
            - path: 实例目录路径
            - created_at: 创建时间（ISO格式）

    示例:
        >>> list_instances()
        [
            {
                'name': 'admin',
                'path': PosixPath('/home/user/.echobot/instances/admin'),
                'created_at': '2024-01-15T10:30:00'
            },
            {
                'name': 'coder',
                'path': PosixPath('/home/user/.echobot/instances/coder'),
                'created_at': '2024-01-15T11:00:00'
            }
        ]
    """
    instances_dir = Path.home() / ".echobot" / "instances"

    if not instances_dir.exists():
        return []

    instances = []
    for item in instances_dir.iterdir():
        if item.is_dir() and validate_instance_name(item.name):
            # 获取目录的创建时间
            stat = item.stat()
            created_at = datetime.fromtimestamp(stat.st_ctime).isoformat()

            instances.append({"name": item.name, "path": item, "created_at": created_at})

    # 按名称排序
    instances.sort(key=lambda x: x["name"])
    return instances


def copy_instance(source: str, target: str) -> None:
    """
    复制实例到新的名称。

    完整复制源实例的所有内容到目标实例，包括：
    - 配置文件
    - 会话历史
    - 工作区文件
    - 定时任务

    参数:
        source: 源实例名称
        target: 目标实例名称

    异常:
        ValueError:
            - 如果源实例不存在
            - 如果目标实例已存在
            - 如果实例名称不合法

    示例:
        >>> copy_instance("admin", "admin-backup")
        # 将 admin 实例完整复制到 admin-backup
    """
    # 验证源实例名称
    if not validate_instance_name(source):
        raise ValueError(f"Invalid source instance name: '{source}'")

    # 验证目标实例名称
    if not validate_instance_name(target):
        raise ValueError(f"Invalid target instance name: '{target}'")

    # 检查源实例是否存在
    source_dir = get_instance_dir(source)
    if not source_dir.exists():
        raise ValueError(f"Source instance does not exist: '{source}'")

    # 检查目标实例是否已存在
    target_dir = get_instance_dir(target)
    if target_dir.exists():
        raise ValueError(f"Target instance already exists: '{target}'")

    # 复制整个实例目录
    shutil.copytree(source_dir, target_dir)


def delete_instance(instance_name: str) -> None:
    """
    删除指定实例。

    完全删除实例目录及其所有内容，包括：
    - 配置文件
    - 会话历史
    - 工作区文件
    - 定时任务

    警告：此操作不可恢复！

    参数:
        instance_name: 要删除的实例名称

    异常:
        ValueError: 如果实例名称不合法或实例不存在

    示例:
        >>> delete_instance("old-instance")
        # 删除 old-instance 实例
    """
    # 验证实例名称
    if not validate_instance_name(instance_name):
        raise ValueError(f"Invalid instance name: '{instance_name}'")

    # 检查实例是否存在
    instance_dir = get_instance_dir(instance_name)
    if not instance_dir.exists():
        raise ValueError(f"Instance does not exist: '{instance_name}'")

    # 删除实例目录
    shutil.rmtree(instance_dir)
