"""
Bot Manager API 路由
提供模型配置、Bot 管理、设置管理、MCP 服务器等功能的 API
"""
import json
import logging
import uuid
import hashlib
import secrets
import os
import shutil
from datetime import datetime, timedelta
from pathlib import Path
from typing import Optional, List
from fastapi import APIRouter, HTTPException, Header
from pydantic import BaseModel

from agent.db_pool_manager import get_db_pool_manager
from utils.fastapi_utils import extract_api_key_from_auth
from utils.new_api_proxy import get_new_api_proxy
from utils.settings import SINGLE_AGENT_MODE, TEMPLATE_BOT_ID, TEMPLATE_BOT_NAME, MASTERKEY

logger = logging.getLogger('app')

router = APIRouter()

# ============== 辅助函数 ==============

def copy_skills_folder(source_bot_id: str, target_bot_id: str) -> bool:
    """
    复制智能体的 skills 文件夹

    Args:
        source_bot_id: 源智能体 ID
        target_bot_id: 目标智能体 ID

    Returns:
        bool: 是否成功复制
    """
    try:
        source_skills_path = os.path.join('projects', 'uploads', source_bot_id, 'skills')
        target_skills_path = os.path.join('projects', 'uploads', target_bot_id, 'skills')

        if os.path.exists(source_skills_path):
            # 如果目标目录已存在，先删除
            if os.path.exists(target_skills_path):
                shutil.rmtree(target_skills_path)

            # 复制整个 skills 文件夹
            shutil.copytree(source_skills_path, target_skills_path)
            logger.info(f"Copied skills folder from {source_bot_id} to {target_bot_id}")
            return True
        else:
            logger.info(f"Source skills folder not found: {source_skills_path}")
            return False
    except Exception as e:
        logger.error(f"Failed to copy skills folder: {e}")
        return False


async def get_or_create_single_agent_bot(user_id: str, pool):
    """
    获取或创建用户的单智能体 bot

    子账号直接使用主账号的智能体，不进行复制

    Args:
        user_id: 用户 ID
        pool: 数据库连接池

    Returns:
        dict: { enabled: bool, bot_name: str, bot_id: str } 或 { enabled: False }
    """
    if not SINGLE_AGENT_MODE:
        return {"enabled": False}

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 检查用户信息（包括子账号状态和主账号ID）
            await cursor.execute("""
                SELECT single_agent_bot_id, is_subaccount, parent_id
                FROM agent_user
                WHERE id = %s
            """, (user_id,))
            row = await cursor.fetchone()

            if not row:
                return {"enabled": False}

            user_bot_id, is_subaccount, parent_id = row

            # 子账号直接使用主账号的智能体
            if is_subaccount and parent_id:
                await cursor.execute("""
                    SELECT single_agent_bot_id
                    FROM agent_user
                    WHERE id = %s
                """, (parent_id,))
                parent_row = await cursor.fetchone()

                if parent_row and parent_row[0]:
                    return {
                        "enabled": True,
                        "bot_name": TEMPLATE_BOT_NAME,
                        "bot_id": str(parent_row[0])
                    }
                else:
                    # 主账号也没有智能体，返回空
                    return {"enabled": False}

            # 主账号逻辑：检查是否已有 bot_id
            user_bot_id = row[0] if row and row[0] else None

            # 如果用户没有 bot_id，自动复制模板
            if not user_bot_id:
                if not TEMPLATE_BOT_ID:
                    logger.warning("TEMPLATE_BOT_ID not configured")
                    return {"enabled": False}

                try:
                    # 获取模板 bot
                    await cursor.execute("""
                        SELECT id, name, settings
                        FROM agent_bots
                        WHERE id = %s AND is_published = TRUE
                    """, (TEMPLATE_BOT_ID,))
                    template = await cursor.fetchone()

                    if not template:
                        logger.warning(f"Template bot {TEMPLATE_BOT_ID} not found")
                        return {"enabled": False}

                    template_id, template_name, template_settings = template
                    settings = template_settings if template_settings else {}

                    # 创建新 bot
                    new_bot_id = str(uuid.uuid4())

                    # 复制设置（不复制知识库）
                    new_settings = {
                        'model_id': settings.get('model_id'),
                        'language': settings.get('language', 'zh'),
                        'avatar_url': settings.get('avatar_url'),
                        'description': settings.get('description'),
                        'suggestions': settings.get('suggestions'),
                        'system_prompt': settings.get('system_prompt'),
                        'enable_memori': settings.get('enable_memori', False),
                        'enable_thinking': settings.get('enable_thinking', False),
                        'tool_response': settings.get('tool_response', False),
                        'skills': settings.get('skills'),
                        'shell_env': {k: '' for k in (settings.get('shell_env') or {})},
                    }

                    # 插入新 bot
                    await cursor.execute("""
                        INSERT INTO agent_bots (name, bot_id, owner_id, settings, copied_from)
                        VALUES (%s, %s, %s, %s, %s)
                        RETURNING id
                    """, (TEMPLATE_BOT_NAME, new_bot_id, user_id, json.dumps(new_settings), template_id))
                    new_row = await cursor.fetchone()
                    user_bot_id = new_row[0]

                    # 更新用户的 single_agent_bot_id
                    await cursor.execute("""
                        UPDATE agent_user
                        SET single_agent_bot_id = %s
                        WHERE id = %s
                    """, (user_bot_id, user_id))

                    # 复制 skills 文件夹
                    copy_skills_folder(str(template_id), str(new_bot_id))

                    await conn.commit()

                    logger.info(f"Created single agent bot {user_bot_id} for user {user_id}")

                except Exception as e:
                    logger.error(f"Failed to copy single agent bot: {e}")
                    return {"enabled": False}

            return {
                "enabled": True,
                "bot_name": TEMPLATE_BOT_NAME,
                "bot_id": str(user_bot_id)
            }

# ============== Admin 配置 ==============
ADMIN_USERNAME = "admin"
ADMIN_PASSWORD = "Admin123"  # 生产环境应使用环境变量
TOKEN_EXPIRE_HOURS = 24


# ============== 认证函数 ==============

def verify_auth(authorization: Optional[str]) -> None:
    """
    验证请求认证

    Args:
        authorization: Authorization header 值

    Raises:
        HTTPException: 认证失败时抛出 401 错误
    """
    provided_token = extract_api_key_from_auth(authorization)
    if not provided_token:
        raise HTTPException(
            status_code=401,
            detail="Authorization header is required"
        )


# ============== 用户认证辅助函数 ==============

def hash_password(password: str) -> str:
    """
    使用 SHA256 哈希密码

    Args:
        password: 明文密码

    Returns:
        str: 哈希后的密码
    """
    return hashlib.sha256(password.encode()).hexdigest()


async def verify_user_auth(authorization: Optional[str]) -> tuple[bool, Optional[str], Optional[str]]:
    """
    验证用户认证

    支持两种认证方式：
    1. MASTERKEY - 使用 settings.MASTERKEY 进行鉴权，视为超级管理员
    2. 用户 Token - 从数据库验证用户 token

    Args:
        authorization: Authorization header 值

    Returns:
        tuple[bool, Optional[str], Optional[str]]: (是否有效, 用户ID, 用户名)
    """
    provided_token = extract_api_key_from_auth(authorization)
    if not provided_token:
        return False, None, None

    # 检查是否为 masterkey
    if MASTERKEY and provided_token == MASTERKEY:
        return True, "__masterkey__", "masterkey"

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 检查 token 是否有效且未过期
            await cursor.execute("""
                SELECT u.id, u.username, t.expires_at
                FROM agent_user_tokens t
                JOIN agent_user u ON t.user_id = u.id
                WHERE t.token = %s
                AND t.expires_at > NOW()
                AND u.is_active = TRUE
            """, (provided_token,))
            row = await cursor.fetchone()

            if not row:
                return False, None, None

            return True, str(row[0]), row[1]


async def get_user_id_from_token(authorization: Optional[str]) -> Optional[str]:
    """
    从 token 获取用户 ID

    Args:
        authorization: Authorization header 值

    Returns:
        Optional[str]: 用户 ID，无效时返回 None
    """
    valid, user_id, _ = await verify_user_auth(authorization)
    return user_id if valid else None


# ============== 权限检查辅助函数 ==============

async def is_admin_user(authorization: Optional[str]) -> bool:
    """
    检查当前请求是否来自管理员（is_admin=True 的用户）

    Args:
        authorization: Authorization header 值

    Returns:
        bool: 是否是管理员
    """
    user_valid, user_id, _ = await verify_user_auth(authorization)
    if not user_valid or not user_id:
        return False

    # masterkey 用户视为管理员
    if user_id == "__masterkey__":
        return True

    pool = get_db_pool_manager().pool
    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT is_admin FROM agent_user WHERE id = %s
            """, (user_id,))
            row = await cursor.fetchone()
            return row and row[0]


async def is_subaccount_user(authorization: Optional[str]) -> bool:
    """
    检查当前请求是否来自子账号

    Args:
        authorization: Authorization header 值

    Returns:
        bool: 是否是子账号
    """
    user_valid, user_id, _ = await verify_user_auth(authorization)
    if not user_valid or not user_id:
        return False

    pool = get_db_pool_manager().pool
    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT is_subaccount FROM agent_user WHERE id = %s
            """, (user_id,))
            row = await cursor.fetchone()
            return row and row[0]


async def get_parent_user_id(user_id: str) -> Optional[str]:
    """
    获取用户的主账号ID（如果是子账号）

    Args:
        user_id: 用户 UUID

    Returns:
        Optional[str]: 主账号ID，如果不是子账号则返回自身ID
    """
    # masterkey 用户无需查询数据库
    if user_id == "__masterkey__":
        return user_id

    pool = get_db_pool_manager().pool
    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT parent_id FROM agent_user WHERE id = %s
            """, (user_id,))
            row = await cursor.fetchone()
            if row and row[0]:
                return str(row[0])
            return user_id


async def check_bot_access(bot_id: str, user_id: str, required_permission: str) -> bool:
    """
    检查用户对 Bot 的访问权限

    子账号可以访问主账号的所有 Bot

    Args:
        bot_id: Bot UUID
        user_id: 用户 UUID
        required_permission: 需要的权限 ('read', 'write', 'share', 'delete')

    Returns:
        bool: 是否有权限
    """
    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 获取用户的主账号ID（如果是子账号）
            effective_user_id = await get_parent_user_id(user_id)
            # 如果返回的是自身ID，说明不是子账号，保持原样
            # 如果返回的是其他ID，说明是子账号，使用主账号ID检查权限

            # 检查是否是所有者（包括主账号的所有权）
            await cursor.execute("""
                SELECT id FROM agent_bots
                WHERE id = %s AND owner_id = %s
            """, (bot_id, effective_user_id))
            if await cursor.fetchone():
                return True

            # 检查是否是公开到广场的智能体（所有人都可以 read）
            if required_permission == 'read':
                await cursor.execute("""
                    SELECT is_published FROM agent_bots WHERE id = %s
                """, (bot_id,))
                pub_row = await cursor.fetchone()
                if pub_row and pub_row[0]:
                    return True

            # 检查是否在分享列表中（同��检查过期时间）
            await cursor.execute("""
                SELECT role, expires_at FROM bot_shares
                WHERE bot_id = %s AND user_id = %s
            """, (bot_id, user_id))
            row = await cursor.fetchone()

            if not row:
                return False

            role, expires_at = row

            # 检查是否已过期
            if expires_at is not None:
                # 获取当前时间（考虑时区）
                from datetime import datetime, timezone
                now = datetime.now(timezone.utc)
                if expires_at < now:
                    # 分享已过期，拒绝访问
                    return False

            # 权限矩阵
            permissions = {
                'viewer': ['read'],
                'editor': ['read', 'write'],
                'owner': ['read', 'write', 'share', 'delete']
            }

            return required_permission in permissions.get(role, [])


async def is_bot_owner(bot_id: str, user_id: str) -> bool:
    """
    检查用户是否是 Bot 的所有者

    子账号可以"拥有"主账号的 Bot（用于编辑权限）

    Args:
        bot_id: Bot UUID (可能是 bot_id 字段）
        user_id: 用户 UUID

    Returns:
        bool: 是否是所有者
    """
    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 获取用户的主账号ID（如果是子账号）
            effective_user_id = await get_parent_user_id(user_id)

            await cursor.execute("""
                SELECT id FROM agent_bots
                WHERE id = %s AND owner_id = %s
            """, (bot_id, effective_user_id))
            return await cursor.fetchone() is not None


async def get_user_bot_role(bot_id: str, user_id: str) -> Optional[str]:
    """
    获取用户在 Bot 中的角色

    子账号被视为 Bot 的所有者（如果主账号是所有者）

    Args:
        bot_id: Bot UUID
        user_id: 用户 UUID

    Returns:
        Optional[str]: 'owner', 'editor', 'viewer' 或 None
    """
    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 获取用户的主账号ID（如果是子账号）
            effective_user_id = await get_parent_user_id(user_id)

            # 检查是否是所有者（包括主账号的所有权）
            await cursor.execute("""
                SELECT id FROM agent_bots
                WHERE id = %s AND owner_id = %s
            """, (bot_id, effective_user_id))
            if await cursor.fetchone():
                return 'owner'

            # 检查分享角色
            await cursor.execute("""
                SELECT role FROM bot_shares
                WHERE bot_id = %s AND user_id = %s
            """, (bot_id, user_id))
            row = await cursor.fetchone()

            return row[0] if row else None


# ============== Pydantic Models ==============

# --- Admin 登录相关 ---
class AdminLoginRequest(BaseModel):
    """管理员登录请求"""
    username: str
    password: str


class AdminLoginResponse(BaseModel):
    """管理员登录响应"""
    token: str
    username: str
    expires_at: str


class AdminVerifyResponse(BaseModel):
    """管理员验证响应"""
    valid: bool
    username: Optional[str] = None


# --- 用户认证相关 ---
class UserRegisterRequest(BaseModel):
    """用户注册请求"""
    username: str
    email: Optional[str] = None
    password: str
    invitation_code: str  # 邀请制注册需要邀请码


class UserLoginRequest(BaseModel):
    """用户登录请求"""
    username: str
    password: str


class UserLoginResponse(BaseModel):
    """用户登录响应"""
    token: str
    user_id: str
    username: str
    email: Optional[str] = None
    is_admin: bool = False
    is_subaccount: bool = False  # 是否是子账号
    parent_id: Optional[str] = None  # 主账号ID
    expires_at: str
    single_agent: Optional[dict] = None  # 单智能体模式配置


class UserVerifyResponse(BaseModel):
    """用户验证响应"""
    valid: bool
    user_id: Optional[str] = None
    username: Optional[str] = None
    is_admin: bool = False
    is_subaccount: bool = False  # 是否是子账号


class UserInfoResponse(BaseModel):
    """用户信息响应"""
    id: str
    username: str
    email: Optional[str] = None
    is_admin: bool = False
    is_subaccount: bool = False  # 是否是子账号
    parent_id: Optional[str] = None  # 主账号ID
    created_at: str
    last_login: Optional[str] = None


class UserSearchResponse(BaseModel):
    """用户搜索响应"""
    id: str
    username: str
    email: Optional[str] = None


# --- 子账号相关 ---
class SubAccountCreateRequest(BaseModel):
    """创建子账号请求"""
    username: str
    password: str
    email: Optional[str] = None


class SubAccountListItem(BaseModel):
    """子账号列表项"""
    id: str
    username: str
    email: Optional[str] = None
    is_active: bool
    created_at: str
    last_login: Optional[str] = None


class UserProfileUpdateRequest(BaseModel):
    """用户更新个人信息请求"""
    username: Optional[str] = None
    email: Optional[str] = None


class ChangePasswordRequest(BaseModel):
    """用户修改密码请求"""
    old_password: str
    new_password: str


# --- 模型相关（已废弃，模型管理已迁移到 New API）---


# --- Bot 相关 ---
class BotCreate(BaseModel):
    """创建 Bot 请求"""
    name: str


class BotUpdate(BaseModel):
    """更新 Bot 请求"""
    name: Optional[str] = None
    bot_id: Optional[str] = None


class BotResponse(BaseModel):
    """Bot 响应"""
    id: str
    name: str
    bot_id: str
    is_owner: bool = False
    is_shared: bool = False
    is_published: bool = False  # 是否发布到广场
    copied_from: Optional[str] = None  # 复制来源的bot id
    owner: Optional[dict] = None  # {id, username}
    role: Optional[str] = None  # 'viewer', 'editor', None for owner
    shared_at: Optional[str] = None
    expires_at: Optional[str] = None  # 分享过期时间
    description: Optional[str] = None  # 从 settings 中提取
    avatar_url: Optional[str] = None  # 从 settings 中提取
    created_at: str
    updated_at: str


# --- Bot 设置相关 ---
class BotSettingsUpdate(BaseModel):
    """更新 Bot 设置请求"""
    model_id: Optional[str] = None
    language: Optional[str] = None
    avatar_url: Optional[str] = None
    description: Optional[str] = None
    suggestions: Optional[List[str]] = None
    dataset_ids: Optional[List[str]] = None  # 改为数组类型，支持多选知识库
    system_prompt: Optional[str] = None
    enable_memori: Optional[bool] = None
    enable_thinking: Optional[bool] = None
    tool_response: Optional[bool] = None
    skills: Optional[str] = None
    is_published: Optional[bool] = None  # 是否发布到广场
    shell_env: Optional[dict] = None  # 自定义 shell 环境变量
    voice_speaker: Optional[str] = None  # 语音音色
    voice_system_role: Optional[str] = None  # 语音对话系统角色
    voice_speaking_style: Optional[str] = None  # 语音说话风格


class ModelInfo(BaseModel):
    """模型信息"""
    id: str
    name: str
    provider: str
    model: str
    server: Optional[str]
    api_key: Optional[str]  # 掩码显示


class NewAPIModelResponse(BaseModel):
    """New API 模型响应"""
    id: str
    object: str = "model"
    created: Optional[int] = None
    owned_by: str = "system"


class BotSettingsResponse(BaseModel):
    """Bot 设置响应"""
    bot_id: str
    name: str  # bot 名称
    model_id: Optional[str]
    model: Optional[ModelInfo]  # 关联的模型信息
    models: List[NewAPIModelResponse] = []  # 用户可用的模型列表
    language: str
    avatar_url: Optional[str]
    description: Optional[str]
    suggestions: Optional[List[str]]
    dataset_ids: Optional[List[str]]  # 改为数组类型
    system_prompt: Optional[str]
    enable_memori: bool
    enable_thinking: bool
    tool_response: bool
    skills: Optional[str]
    shell_env: Optional[dict] = None  # 自定义 shell 环境变量
    is_published: bool = False  # 是否发布到广场
    is_owner: bool = True  # 是否是所有者
    copied_from: Optional[str] = None  # 复制来源的bot id
    voice_speaker: Optional[str] = None  # 语音音色
    voice_system_role: Optional[str] = None  # 语音对话系统角色
    voice_speaking_style: Optional[str] = None  # 语音说话风格
    updated_at: str


# --- 广场相关 ---
class MarketplaceBotResponse(BaseModel):
    """广场 Bot 响应（公开信息）"""
    id: str
    name: str
    description: Optional[str] = None
    avatar_url: Optional[str] = None
    owner_name: Optional[str] = None
    suggestions: Optional[List[str]] = None
    copy_count: int = 0  # 被复制次数
    created_at: str
    updated_at: str


class MarketplaceListResponse(BaseModel):
    """广场列表响应"""
    bots: List[MarketplaceBotResponse]
    total: int


# --- 会话相关 ---
class SessionCreate(BaseModel):
    """创建会话请求"""
    title: Optional[str] = None


class SessionResponse(BaseModel):
    """会话响应"""
    id: str
    bot_id: str
    title: Optional[str]
    created_at: str
    updated_at: str


# --- MCP 相关 ---
class MCPServerCreate(BaseModel):
    """创建 MCP 服务器请求"""
    name: str
    type: str
    config: dict
    enabled: bool = True


class MCPServerUpdate(BaseModel):
    """更新 MCP 服务器请求"""
    name: Optional[str] = None
    type: Optional[str] = None
    config: Optional[dict] = None
    enabled: Optional[bool] = None


class MCPServerResponse(BaseModel):
    """MCP 服务器响应"""
    id: str
    bot_id: str
    name: str
    type: str
    config: dict
    enabled: bool
    created_at: str
    updated_at: str


# --- 分享相关 ---
class BotShareCreate(BaseModel):
    """创建分享请求"""
    user_ids: List[str]
    role: str = "viewer"  # 'viewer' or 'editor'
    expires_at: Optional[str] = None  # ISO 8601 格式的过期时间，None 表示永不过期


class BotShareResponse(BaseModel):
    """分享响应"""
    id: str
    bot_id: str
    user_id: str
    username: str
    email: Optional[str] = None
    role: str
    shared_at: str
    shared_by: Optional[str] = None
    expires_at: Optional[str] = None  # 过期时间


class BotSharesListResponse(BaseModel):
    """分享列表响应"""
    bot_id: str
    shares: List[BotShareResponse]



# --- 通用响应 ---
class SuccessResponse(BaseModel):
    """通用成功响应"""
    success: bool
    message: str


# ============== 数据库表初始化 ==============

async def migrate_bot_owner_and_shares():
    """
    迁移 agent_bots 表添加 owner_id 字段，并创建相关表
    """
    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 1. 首先创建 agent_user 表
            await cursor.execute("""
                SELECT EXISTS (
                    SELECT FROM information_schema.tables
                    WHERE table_name = 'agent_user'
                )
            """)
            user_table_exists = (await cursor.fetchone())[0]

            if not user_table_exists:
                logger.info("Creating agent_user table")

                # 创建 agent_user 表
                await cursor.execute("""
                    CREATE TABLE agent_user (
                        id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
                        username VARCHAR(255) UNIQUE NOT NULL,
                        email VARCHAR(255) UNIQUE,
                        password_hash VARCHAR(255) NOT NULL,
                        created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
                        updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
                        last_login TIMESTAMP WITH TIME ZONE,
                        is_active BOOLEAN DEFAULT TRUE,
                        is_admin BOOLEAN DEFAULT FALSE
                    )
                """)

                # 创建索引
                await cursor.execute("CREATE INDEX idx_agent_user_username ON agent_user(username)")
                await cursor.execute("CREATE INDEX idx_agent_user_email ON agent_user(email)")
                await cursor.execute("CREATE INDEX idx_agent_user_is_active ON agent_user(is_active)")

                logger.info("agent_user table created successfully")
            else:
                # 为已存在的表添加 is_admin 字段
                await cursor.execute("""
                    SELECT column_name
                    FROM information_schema.columns
                    WHERE table_name = 'agent_user' AND column_name = 'is_admin'
                """)
                has_admin_column = await cursor.fetchone()
                if not has_admin_column:
                    logger.info("Adding is_admin column to agent_user table")
                    await cursor.execute("""
                        ALTER TABLE agent_user
                        ADD COLUMN is_admin BOOLEAN DEFAULT FALSE
                    """)
                    logger.info("is_admin column added successfully")

            # 3. 添加 new_api_session 字段
            await cursor.execute("""
                SELECT column_name
                FROM information_schema.columns
                WHERE table_name = 'agent_user' AND column_name = 'new_api_session'
            """)
            has_session_column = await cursor.fetchone()
            if not has_session_column:
                logger.info("Adding new_api_session column to agent_user table")
                await cursor.execute("""
                    ALTER TABLE agent_user
                    ADD COLUMN new_api_session VARCHAR(500)
                """)
                logger.info("new_api_session column added successfully")

            # 检查并添加 new_api_user_id 字段
            await cursor.execute("""
                SELECT column_name
                FROM information_schema.columns
                WHERE table_name = 'agent_user' AND column_name = 'new_api_user_id'
            """)
            has_user_id_column = await cursor.fetchone()
            if not has_user_id_column:
                logger.info("Adding new_api_user_id column to agent_user table")
                await cursor.execute("""
                    ALTER TABLE agent_user
                    ADD COLUMN new_api_user_id INTEGER
                """)
                logger.info("new_api_user_id column added successfully")

            # 检查并添加 new_api_token 字段（用于存储 API Key）
            await cursor.execute("""
                SELECT column_name
                FROM information_schema.columns
                WHERE table_name = 'agent_user' AND column_name = 'new_api_token'
            """)
            has_token_column = await cursor.fetchone()
            if not has_token_column:
                logger.info("Adding new_api_token column to agent_user table")
                await cursor.execute("""
                    ALTER TABLE agent_user
                    ADD COLUMN new_api_token VARCHAR(255)
                """)
                logger.info("new_api_token column added successfully")

            # 2. 创建 bot_shares 表
            await cursor.execute("""
                SELECT EXISTS (
                    SELECT FROM information_schema.tables
                    WHERE table_name = 'bot_shares'
                )
            """)
            shares_table_exists = (await cursor.fetchone())[0]

            if not shares_table_exists:
                logger.info("Creating bot_shares table")

                await cursor.execute("""
                    CREATE TABLE bot_shares (
                        id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
                        bot_id UUID NOT NULL REFERENCES agent_bots(id) ON DELETE CASCADE,
                        user_id UUID NOT NULL REFERENCES agent_user(id) ON DELETE CASCADE,
                        shared_by UUID NOT NULL REFERENCES agent_user(id) ON DELETE SET NULL,
                        role VARCHAR(50) DEFAULT 'viewer' CHECK (role IN ('viewer', 'editor')),
                        shared_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
                        expires_at TIMESTAMP WITH TIME ZONE,
                        UNIQUE(bot_id, user_id)
                    )
                """)

                await cursor.execute("CREATE INDEX idx_bot_shares_bot_id ON bot_shares(bot_id)")
                await cursor.execute("CREATE INDEX idx_bot_shares_user_id ON bot_shares(user_id)")
                await cursor.execute("CREATE INDEX idx_bot_shares_shared_by ON bot_shares(shared_by)")

                logger.info("bot_shares table created successfully")
            else:
                # 为已存在的表添加 expires_at 字段
                await cursor.execute("""
                    SELECT column_name
                    FROM information_schema.columns
                    WHERE table_name = 'bot_shares' AND column_name = 'expires_at'
                """)
                has_expires_column = await cursor.fetchone()
                if not has_expires_column:
                    logger.info("Adding expires_at column to bot_shares table")
                    await cursor.execute("""
                        ALTER TABLE bot_shares
                        ADD COLUMN expires_at TIMESTAMP WITH TIME ZONE
                    """)
                    logger.info("expires_at column added successfully")

            # 4. 创建 agent_user_tokens 表
            await cursor.execute("""
                SELECT EXISTS (
                    SELECT FROM information_schema.tables
                    WHERE table_name = 'agent_user_tokens'
                )
            """)
            tokens_table_exists = (await cursor.fetchone())[0]

            if not tokens_table_exists:
                logger.info("Creating agent_user_tokens table")

                await cursor.execute("""
                    CREATE TABLE agent_user_tokens (
                        id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
                        user_id UUID NOT NULL REFERENCES agent_user(id) ON DELETE CASCADE,
                        token VARCHAR(255) NOT NULL UNIQUE,
                        expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
                        created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
                    )
                """)

                await cursor.execute("CREATE INDEX idx_agent_user_tokens_token ON agent_user_tokens(token)")
                await cursor.execute("CREATE INDEX idx_agent_user_tokens_user_id ON agent_user_tokens(user_id)")
                await cursor.execute("CREATE INDEX idx_agent_user_tokens_expires ON agent_user_tokens(expires_at)")

                logger.info("agent_user_tokens table created successfully")

            # 5. 检查 agent_bots 表是否有 owner_id 字段
            await cursor.execute("""
                SELECT column_name
                FROM information_schema.columns
                WHERE table_name = 'agent_bots' AND column_name = 'owner_id'
            """)
            has_owner_column = await cursor.fetchone()

            if not has_owner_column:
                logger.info("Adding owner_id column to agent_bots table")

                # 首先创建或更新默认 admin 用户（密码：admin123）
                default_admin_id = '00000000-0000-0000-0000-000000000001'
                default_admin_password_hash = hash_password('admin123')

                # 先���除可能存在的旧 admin 用户（避免用户名冲突）
                await cursor.execute("DELETE FROM agent_user WHERE username = 'admin' AND id != %s", (default_admin_id,))

                # 创建或更新 admin 用户
                await cursor.execute("""
                    INSERT INTO agent_user (id, username, email, password_hash, is_active, is_admin)
                    VALUES (%s, 'admin', 'admin@local', %s, TRUE, TRUE)
                    ON CONFLICT (id) DO UPDATE SET password_hash = EXCLUDED.password_hash, is_admin = EXCLUDED.is_admin
                """, (default_admin_id, default_admin_password_hash))

                logger.info(f"Default admin user created/updated with password 'admin123'")

                # 添加 owner_id 字段，允许 NULL 以便迁移
                await cursor.execute("""
                    ALTER TABLE agent_bots
                    ADD COLUMN owner_id UUID REFERENCES agent_user(id) ON DELETE SET NULL
                """)

                # 创建索引
                await cursor.execute("CREATE INDEX idx_agent_bots_owner_id ON agent_bots(owner_id)")

                # 将现有的 bots 分配给默认 admin 用户
                await cursor.execute("""
                    UPDATE agent_bots
                    SET owner_id = %s
                    WHERE owner_id IS NULL
                """, (default_admin_id,))

                logger.info("Existing bots assigned to default admin user")

                # 现在将 owner_id 改为 NOT NULL
                await cursor.execute("""
                    ALTER TABLE agent_bots
                    ALTER COLUMN owner_id SET NOT NULL
                """)

                # 为了防止数据丢失，将 ON DELETE SET NULL 改为 ON DELETE RESTRICT
                # 需要先删除约束再重新添加
                await cursor.execute("""
                    ALTER TABLE agent_bots
                    DROP CONSTRAINT agent_bots_owner_id_fkey
                """)
                await cursor.execute("""
                    ALTER TABLE agent_bots
                    ADD CONSTRAINT agent_bots_owner_id_fkey
                    FOREIGN KEY (owner_id) REFERENCES agent_user(id) ON DELETE RESTRICT
                """)

                logger.info("owner_id column added and set to NOT NULL")

            # 确保默认 admin 用户存在（总是执行）
            default_admin_id = '00000000-0000-0000-0000-000000000001'
            default_admin_password_hash = hash_password('admin123')

            # 检查 admin 用户是否已存在
            await cursor.execute("SELECT id, password_hash FROM agent_user WHERE username = 'admin'")
            admin_row = await cursor.fetchone()

            if admin_row:
                existing_id, existing_hash = admin_row
                # 如果密码是旧的 PLACEHOLDER，则更新
                if existing_hash == 'PLACEHOLDER' or existing_hash == '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918':
                    await cursor.execute("""
                        UPDATE agent_user
                        SET password_hash = %s, is_admin = TRUE
                        WHERE username = 'admin'
                    """, (default_admin_password_hash,))
                    logger.info("Updated existing admin user with new password 'admin123'")
            else:
                # 创建新的 admin 用户
                await cursor.execute("""
                    INSERT INTO agent_user (id, username, email, password_hash, is_active, is_admin)
                    VALUES (%s, 'admin', 'admin@local', %s, TRUE, TRUE)
                """, (default_admin_id, default_admin_password_hash))
                logger.info("Created new admin user with password 'admin123'")

            await conn.commit()
            logger.info("Bot owner and shares migration completed successfully")


async def migrate_bot_settings_to_jsonb():
    """
    迁移 agent_bot_settings 表数据到 agent_bots.settings JSONB 字段
    这是一个向后兼容的迁移函数
    """
    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 1. 检查 agent_bots 表是否有 settings 列
            await cursor.execute("""
                SELECT column_name
                FROM information_schema.columns
                WHERE table_name = 'agent_bots' AND column_name = 'settings'
            """)
            has_settings_column = await cursor.fetchone()

            if not has_settings_column:
                logger.info("Migrating agent_bots table: adding settings column")

                # 添加 settings 列
                await cursor.execute("""
                    ALTER TABLE agent_bots
                    ADD COLUMN settings JSONB DEFAULT '{
                        "language": "zh",
                        "enable_memori": false,
                        "enable_thinking": false,
                        "tool_response": false
                    }'::jsonb
                """)

                # 2. 检查旧的 agent_bot_settings 表是否存在
                await cursor.execute("""
                    SELECT EXISTS (
                        SELECT FROM information_schema.tables
                        WHERE table_name = 'agent_bot_settings'
                    )
                """)
                old_table_exists = (await cursor.fetchone())[0]

                if old_table_exists:
                    logger.info("Migrating data from agent_bot_settings to agent_bots.settings")

                    # 3. 迁移旧数据到新字段
                    await cursor.execute("""
                        UPDATE agent_bots b
                        SET settings = jsonb_build_object(
                            'model_id', s.model_id,
                            'language', COALESCE(s.language, 'zh'),
                            'dataset_ids', s.dataset_ids,
                            'system_prompt', s.system_prompt,
                            'enable_memori', COALESCE(s.enable_memori, false),
                            'enable_thinking', false,
                            'tool_response', COALESCE(s.tool_response, false),
                            'skills', s.skills
                        )
                        FROM agent_bot_settings s
                        WHERE b.id = s.bot_id
                    """)

                    logger.info("Data migration completed, dropping old table")

                    # 4. 删除旧的 agent_bot_settings 表
                    await cursor.execute("DROP TABLE IF EXISTS agent_bot_settings CASCADE")

                await conn.commit()
                logger.info("Bot settings migration completed successfully")
            else:
                logger.info("Settings column already exists, skipping migration")


async def migrate_add_marketplace_fields():
    """
    添加智能体广场相关字段到 agent_bots 表
    """
    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 1. 添加 is_published 字段
            await cursor.execute("""
                SELECT column_name
                FROM information_schema.columns
                WHERE table_name = 'agent_bots' AND column_name = 'is_published'
            """)
            has_is_published = await cursor.fetchone()

            if not has_is_published:
                logger.info("Adding is_published column to agent_bots table")
                await cursor.execute("""
                    ALTER TABLE agent_bots
                    ADD COLUMN is_published BOOLEAN DEFAULT FALSE
                """)
                # 创建部分索引，只索引发布的 bots
                await cursor.execute("""
                    CREATE INDEX idx_agent_bots_is_published
                    ON agent_bots(is_published) WHERE is_published = TRUE
                """)
                logger.info("is_published column added successfully")

            # 2. 添加 copied_from 字段
            await cursor.execute("""
                SELECT column_name
                FROM information_schema.columns
                WHERE table_name = 'agent_bots' AND column_name = 'copied_from'
            """)
            has_copied_from = await cursor.fetchone()

            if not has_copied_from:
                logger.info("Adding copied_from column to agent_bots table")
                await cursor.execute("""
                    ALTER TABLE agent_bots
                    ADD COLUMN copied_from UUID REFERENCES agent_bots(id) ON DELETE SET NULL
                """)
                await cursor.execute("""
                    CREATE INDEX idx_agent_bots_copied_from ON agent_bots(copied_from)
                """)
                logger.info("copied_from column added successfully")

            await conn.commit()
            logger.info("Marketplace fields migration completed")


async def migrate_single_agent_mode():
    """
    添加单智能体模式相关字段到 agent_user 表
    """
    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 检查 single_agent_bot_id 字段是否存在
            await cursor.execute("""
                SELECT column_name
                FROM information_schema.columns
                WHERE table_name = 'agent_user' AND column_name = 'single_agent_bot_id'
            """)
            has_single_agent_bot_id = await cursor.fetchone()

            if not has_single_agent_bot_id:
                logger.info("Adding single_agent_bot_id column to agent_user table")
                await cursor.execute("""
                    ALTER TABLE agent_user
                    ADD COLUMN single_agent_bot_id UUID
                """)
                await cursor.execute("""
                    CREATE INDEX IF NOT EXISTS idx_agent_user_single_agent_bot
                    ON agent_user(single_agent_bot_id) WHERE single_agent_bot_id IS NOT NULL
                """)
                logger.info("Single agent mode migration completed")
            else:
                logger.info("single_agent_bot_id column already exists")

            await conn.commit()


async def migrate_subaccount_support():
    """
    添加子账号支持相关字段到 agent_user 表
    """
    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 检查 is_subaccount 字段是否存在
            await cursor.execute("""
                SELECT column_name
                FROM information_schema.columns
                WHERE table_name = 'agent_user' AND column_name = 'is_subaccount'
            """)
            has_is_subaccount = await cursor.fetchone()

            if not has_is_subaccount:
                logger.info("Adding subaccount support columns to agent_user table")
                # 添加 is_subaccount 字段
                await cursor.execute("""
                    ALTER TABLE agent_user
                    ADD COLUMN is_subaccount BOOLEAN DEFAULT FALSE
                """)

                # 添加 parent_id 字段
                await cursor.execute("""
                    ALTER TABLE agent_user
                    ADD COLUMN parent_id UUID REFERENCES agent_user(id) ON DELETE CASCADE
                """)

                # 添加索引
                await cursor.execute("""
                    CREATE INDEX IF NOT EXISTS idx_agent_user_parent_id ON agent_user(parent_id)
                """)
                await cursor.execute("""
                    CREATE INDEX IF NOT EXISTS idx_agent_user_is_subaccount ON agent_user(is_subaccount)
                """)

                # 添加约束防止自引用（使用 DO 块处理约束可能已存在的情况）
                await cursor.execute("""
                    DO $$
                    BEGIN
                        IF NOT EXISTS (
                            SELECT 1 FROM pg_constraint WHERE conname = 'check_not_self_parent'
                        ) THEN
                            ALTER TABLE agent_user
                            ADD CONSTRAINT check_not_self_parent
                            CHECK (parent_id IS NULL OR parent_id != id);
                        END IF;
                    END $$;
                """)

                logger.info("Subaccount support migration completed")
            else:
                logger.info("Subaccount support columns already exist")

            await conn.commit()


async def init_bot_manager_tables():
    """
    初始化 Bot Manager 相关的所有数据库表
    """
    pool = get_db_pool_manager().pool

    # 首先执行迁移（如果需要）
    # 1. Bot settings 迁移
    await migrate_bot_settings_to_jsonb()
    # 2. User 和 shares 迁移
    await migrate_bot_owner_and_shares()
    # 3. Marketplace 字段迁移
    await migrate_add_marketplace_fields()
    # 4. Single Agent Mode 字段迁移
    await migrate_single_agent_mode()
    # 5. Subaccount Support 字段迁移
    await migrate_subaccount_support()

    # SQL 表创建语句
    tables_sql = [
        # admin_tokens 表（用于存储登录 token）
        """
        CREATE TABLE IF NOT EXISTS agent_admin_tokens (
            id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
            username VARCHAR(255) NOT NULL,
            token VARCHAR(255) NOT NULL UNIQUE,
            expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
            created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
        )
        """,
        # admin_tokens 索引
        "CREATE INDEX IF NOT EXISTS idx_agent_admin_tokens_token ON agent_admin_tokens(token)",
        "CREATE INDEX IF NOT EXISTS idx_agent_admin_tokens_expires ON agent_admin_tokens(expires_at)",

        # agent_models 表已废弃，模型管理已迁移到 New API

        # bots 表（合并 settings 为 JSONB 字段）
        """
        CREATE TABLE IF NOT EXISTS agent_bots (
            id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
            name VARCHAR(255) NOT NULL,
            bot_id VARCHAR(255) NOT NULL UNIQUE,
            settings JSONB DEFAULT '{
                "language": "zh",
                "enable_memori": false,
                "enable_thinking": false,
                "tool_response": false
            }'::jsonb,
            created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
            updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
        )
        """,
        # bots 索引
        "CREATE INDEX IF NOT EXISTS idx_agent_bots_bot_id ON agent_bots(bot_id)",

        # mcp_servers 表
        """
        CREATE TABLE IF NOT EXISTS agent_mcp_servers (
            id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
            bot_id UUID REFERENCES agent_bots(id) ON DELETE CASCADE,
            name VARCHAR(255) NOT NULL,
            type VARCHAR(50) NOT NULL,
            config JSONB NOT NULL,
            enabled BOOLEAN DEFAULT TRUE,
            created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
            updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
        )
        """,
        # mcp_servers 索引
        "CREATE INDEX IF NOT EXISTS idx_agent_mcp_servers_bot_id ON agent_mcp_servers(bot_id)",
        "CREATE INDEX IF NOT EXISTS idx_agent_mcp_servers_enabled ON agent_mcp_servers(enabled)",

        # chat_sessions 表
        """
        CREATE TABLE IF NOT EXISTS agent_chat_sessions (
            id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
            bot_id UUID REFERENCES agent_bots(id) ON DELETE CASCADE,
            title VARCHAR(500),
            created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
            updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
        )
        """,
        # chat_sessions 索引
        "CREATE INDEX IF NOT EXISTS idx_agent_chat_sessions_bot_id ON agent_chat_sessions(bot_id)",
        "CREATE INDEX IF NOT EXISTS idx_agent_chat_sessions_created ON agent_chat_sessions(created_at DESC)",
    ]

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            for sql in tables_sql:
                await cursor.execute(sql)
            await conn.commit()

    logger.info("Bot Manager tables initialized successfully")


# ============== 辅助函数 ==============

def mask_api_key(api_key: Optional[str]) -> Optional[str]:
    """对 API Key 进行掩码处理"""
    if not api_key:
        return None
    if len(api_key) <= 8:
        return "****"
    return api_key[:4] + "****" + api_key[-4:]


def datetime_to_str(dt: datetime) -> str:
    """将 datetime 转换为 ISO 格式字符串"""
    return dt.isoformat() if dt else ""


# ============== 模型管理 API（已废弃，已迁移到 New API）=============

# 以下模型管理接口已被移除，现在使用 /api/v1/newapi/models 从 New API 获取模型列表
# - GET /api/v1/models
# - POST /api/v1/models
# - PUT /api/v1/models/{model_id}
# - DELETE /api/v1/models/{model_id}
# - PATCH /api/v1/models/{model_id}/default

# ============== Bot 管理 API ==============

@router.get("/api/v1/bots", response_model=List[BotResponse])
async def get_bots(authorization: Optional[str] = Header(None)):
    """
    获取所有 Bot（拥有的和分享给我的）

    子账号可以看到主账号的所有 Bot

    Args:
        authorization: Bearer token

    Returns:
        List[BotResponse]: Bot 列表
    """
    user_valid, user_id, user_username = await verify_user_auth(authorization)

    if not user_valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 获取用户的主账号ID（如果是子账号）
            await cursor.execute("""
                SELECT COALESCE(parent_id, id) as effective_owner_id
                FROM agent_user
                WHERE id = %s
            """, (user_id,))
            row = await cursor.fetchone()
            effective_owner_id = row[0] if row else user_id

            # 用户可以看到：
            # 1. 自己拥有的 Bot
            # 2. 主账号拥有的 Bot（如果是子账号）
            # 3. 分享给自己的 Bot（未过期）
            await cursor.execute("""
                SELECT DISTINCT b.id, b.name, b.bot_id, b.created_at, b.updated_at, b.settings,
                       u.id as owner_id, u.username as owner_username,
                       s.role, s.shared_at, s.expires_at,
                       b.is_published, b.copied_from
                FROM agent_bots b
                LEFT JOIN agent_user u ON b.owner_id = u.id
                LEFT JOIN bot_shares s ON b.id = s.bot_id AND s.user_id = %s
                WHERE b.owner_id = %s
                   OR b.owner_id = %s
                   OR (s.user_id IS NOT NULL
                       AND s.user_id = %s
                       AND (s.expires_at IS NULL OR s.expires_at > NOW()))
                ORDER BY b.created_at DESC
            """, (user_id, user_id, effective_owner_id, user_id))
            rows = await cursor.fetchall()

            return [
                BotResponse(
                    id=str(row[0]),
                    name=row[1],
                    bot_id=str(row[0]),
                    is_owner=(row[6] is not None and str(row[6]) in (user_id, effective_owner_id)),
                    is_shared=(row[6] is not None and str(row[6]) != user_id and str(row[6]) != effective_owner_id and row[8] is not None),
                    is_published=row[11] if row[11] else False,
                    copied_from=str(row[12]) if row[12] else None,
                    owner={"id": str(row[6]), "username": row[7]} if row[6] is not None else None,
                    role=row[8] if row[8] is not None else None,
                    shared_at=datetime_to_str(row[9]) if row[9] is not None else None,
                    expires_at=row[10].isoformat() if row[10] is not None else None,
                    description=row[5].get('description') if row[5] else None,
                    avatar_url=row[5].get('avatar_url') if row[5] else None,
                    created_at=datetime_to_str(row[3]),
                    updated_at=datetime_to_str(row[4])
                )
                for row in rows
            ]


@router.post("/api/v1/bots", response_model=BotResponse)
async def create_bot(request: BotCreate, authorization: Optional[str] = Header(None)):
    """
    创建新 Bot

    Args:
        request: Bot 创建请求
        authorization: Bearer token

    Returns:
        BotResponse: 创建的 Bot 信息
    """
    user_valid, user_id, user_username = await verify_user_auth(authorization)

    if not user_valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    pool = get_db_pool_manager().pool

    # 自动生成 bot_id
    bot_id = str(uuid.uuid4())

    # 获取用户的主账号ID（如果是子账号，新 bot 归属主账号）
    owner_id = await get_parent_user_id(user_id)

    try:
        async with pool.connection() as conn:
            async with conn.cursor() as cursor:
                await cursor.execute("""
                    INSERT INTO agent_bots (name, bot_id, owner_id)
                    VALUES (%s, %s, %s)
                    RETURNING id, created_at, updated_at, owner_id
                """, (request.name, bot_id, owner_id))
                row = await cursor.fetchone()
                await conn.commit()

                return BotResponse(
                    id=str(row[0]),
                    name=request.name,
                    bot_id=bot_id,
                    is_owner=True,
                    is_shared=False,
                    owner={"id": str(owner_id), "username": user_username} if owner_id else None,
                    created_at=datetime_to_str(row[1]),
                    updated_at=datetime_to_str(row[2])
                )
    except Exception as e:
        if "duplicate key" in str(e):
            raise HTTPException(status_code=400, detail="Bot ID already exists")
        raise


@router.put("/api/v1/bots/{bot_uuid}", response_model=BotResponse)
async def update_bot(
    bot_uuid: str,
    request: BotUpdate,
    authorization: Optional[str] = Header(None)
):
    """
    更新 Bot（仅所有者可以更新）

    Args:
        bot_uuid: Bot 内部 UUID
        request: Bot 更新请求
        authorization: Bearer token

    Returns:
        BotResponse: 更新后的 Bot 信息
    """
    user_valid, user_id, user_username = await verify_user_auth(authorization)

    if not user_valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    # 检查是否是管理员
    is_admin = await is_admin_user(authorization)

    # 非管理员需要检查所有权
    if not is_admin:
        if not await is_bot_owner(bot_uuid, user_id):
            raise HTTPException(
                status_code=403,
                detail="Only bot owner can update"
            )

    pool = get_db_pool_manager().pool

    # 构建更新字段
    update_fields = []
    values = []

    if request.name is not None:
        update_fields.append("name = %s")
        values.append(request.name)
    if request.bot_id is not None:
        update_fields.append("bot_id = %s")
        values.append(request.bot_id)

    if not update_fields:
        raise HTTPException(status_code=400, detail="No fields to update")

    update_fields.append("updated_at = NOW()")
    values.append(bot_uuid)

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute(f"""
                UPDATE agent_bots
                SET {', '.join(update_fields)}
                WHERE id = %s
                RETURNING id, name, bot_id, created_at, updated_at
            """, values)
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(status_code=404, detail="Bot not found")

            await conn.commit()

            return BotResponse(
                id=str(row[0]),
                name=row[1],
                bot_id=row[2],
                is_owner=True,
                is_shared=False,
                created_at=datetime_to_str(row[3]),
                updated_at=datetime_to_str(row[4])
            )


@router.delete("/api/v1/bots/{bot_uuid}", response_model=SuccessResponse)
async def delete_bot(bot_uuid: str, authorization: Optional[str] = Header(None)):
    """
    删除 Bot（仅所有者可以删除，级联删除相关设置、会话、MCP 配置等）

    Args:
        bot_uuid: Bot 内部 UUID
        authorization: Bearer token

    Returns:
        SuccessResponse: 删除结果
    """
    user_valid, user_id, user_username = await verify_user_auth(authorization)

    if not user_valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    # 检查是否是管理员
    is_admin = await is_admin_user(authorization)

    # 非管理员需要检查所有权
    if not is_admin:
        if not await is_bot_owner(bot_uuid, user_id):
            raise HTTPException(
                status_code=403,
                detail="Only bot owner can delete"
            )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("DELETE FROM agent_bots WHERE id = %s RETURNING id", (bot_uuid,))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(status_code=404, detail="Bot not found")

            await conn.commit()

            return SuccessResponse(success=True, message="Bot deleted successfully")


# ============== Bot 设置 API ==============

@router.get("/api/v1/bots/{bot_uuid}/settings", response_model=BotSettingsResponse)
async def get_bot_settings(bot_uuid: str, authorization: Optional[str] = Header(None)):
    """
    获取 Bot 设置（所有者和 editor 可以查看）

    Args:
        bot_uuid: Bot 内部 UUID
        authorization: Bearer token

    Returns:
        BotSettingsResponse: Bot 设置信息
    """
    user_valid, user_id, user_username = await verify_user_auth(authorization)

    if not user_valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    # 检查是否是管理员
    is_admin = await is_admin_user(authorization)

    # 如果是普通用户（非 admin），检查是否有 read 权限
    if not is_admin:
        if not await check_bot_access(bot_uuid, user_id, 'read'):
            raise HTTPException(
                status_code=403,
                detail="You don't have access to this bot"
            )

    pool = get_db_pool_manager().pool

    # 获取用户可用的模型列表
    models_list = []
    try:
        if user_id != "__masterkey__":
            async with pool.connection() as conn:
                async with conn.cursor() as cursor:
                    # 获取用户的 new_api_session 和 new_api_user_id（子账号使用主账号的）
                    effective_user_id = await get_parent_user_id(user_id)
                    await cursor.execute("""
                        SELECT new_api_session, new_api_user_id
                        FROM agent_user
                        WHERE id = %s
                    """, (effective_user_id,))
                    row = await cursor.fetchone()

                    if row and row[0] and row[1]:
                        new_api_session = row[0]
                        new_api_user_id = row[1]

                        # 调用 New API 获取模型列表
                        proxy = get_new_api_proxy()
                        cookies = {"session": new_api_session}

                        result = await proxy.get_user_models(cookies, new_api_user_id)

                        if result.get("success"):
                            data = result.get("data", [])
                            if isinstance(data, list):
                                for model in data:
                                    models_list.append(NewAPIModelResponse(
                                        id=model if isinstance(model, str) else model.get("id", ""),
                                        object="model",
                                        created=None,
                                        owned_by="system"
                                    ))
    except Exception as e:
        # 获取模型列表失败不影响主流程，返回空列表
        print(f"Failed to fetch models: {e}")

    # 获取模型 ID 列表用于检查
    available_model_ids = [m.id for m in models_list]

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT id, name, settings, updated_at, is_published, copied_from, owner_id
                FROM agent_bots
                WHERE id = %s
            """, (bot_uuid,))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(status_code=404, detail="Bot not found")

            bot_id, bot_name, settings_json, updated_at, is_published, copied_from, owner_id = row
            settings = settings_json if settings_json else {}

            # 判断当前用户是否是所有者（子账号使用主账号ID判断，masterkey 视为所有者）
            if user_id == "__masterkey__":
                is_owner = True
            else:
                effective_user_id = await get_parent_user_id(user_id)
                is_owner = (str(owner_id) == str(effective_user_id))

            # 检查 model_id 是否在可用模型列表中
            model_id = settings.get('model_id')
            model_needs_update = False

            if model_id and available_model_ids and model_id not in available_model_ids:
                # 模型已下线，需要更新为第一个可用模型
                print(f"Bot {bot_uuid} has outdated model {model_id}, updating to first available model")
                if models_list:
                    model_id = models_list[0].id
                    model_needs_update = True

            # 如果没有 model_id 或需要更新，使用第一个可用模型
            if not model_id and models_list:
                model_id = models_list[0].id
                model_needs_update = True

            # 如果需要更新模型，保存到数据库
            if model_needs_update and is_owner:
                settings['model_id'] = model_id
                await cursor.execute("""
                    UPDATE agent_bots
                    SET settings = %s, updated_at = NOW()
                    WHERE id = %s
                """, (json.dumps(settings), bot_uuid))

            # 获取关联的模型信息
            model_info = None
            if model_id:
                model_info = ModelInfo(
                    id=model_id,
                    name=model_id,
                    provider=model_id.split('/')[0] if '/' in model_id else 'new-api',
                    model=model_id.split('/')[-1] if '/' in model_id else model_id,
                    server=None,
                    api_key=None
                )

            # 处理 dataset_ids
            # 单智能体模式：加载用户的所有知识库（子账号使用主账号的知识库）
            # 普通模式：从 settings 读取
            if SINGLE_AGENT_MODE and user_id != "__masterkey__":
                effective_user_id_for_ds = await get_parent_user_id(user_id) if user_id != "__masterkey__" else user_id
                await cursor.execute("""
                    SELECT dataset_id
                    FROM user_datasets
                    WHERE user_id = %s
                    ORDER BY created_at DESC
                """, (effective_user_id_for_ds,))
                user_datasets = await cursor.fetchall()
                dataset_ids = [row[0] for row in user_datasets] if user_datasets else []
            else:
                dataset_ids = settings.get('dataset_ids')
                if dataset_ids and isinstance(dataset_ids, str):
                    dataset_ids = [id.strip() for id in dataset_ids.split(',') if id.strip()]
                elif not dataset_ids:
                    dataset_ids = None

            # 扫描 skills 需要的环境变量并合并到 shell_env
            shell_env = settings.get('shell_env') or {}
            skills_list = settings.get('skills')
            if skills_list:
                from utils.multi_project_manager import scan_skill_env_keys
                # skills 可能是逗号分隔的字符串，需要拆分成列表
                if isinstance(skills_list, str):
                    skills_names = [s.strip() for s in skills_list.split(',') if s.strip()]
                else:
                    skills_names = skills_list
                required_keys = scan_skill_env_keys(bot_uuid, skills_names, Path("projects"))
                for key in required_keys:
                    if key not in shell_env:
                        shell_env[key] = ''
                # 清理不在 skill 所需变量中且值为空的环境变量
                shell_env = {k: v for k, v in shell_env.items() if v or k in required_keys}

            # 对于值为空的环境变量，尝试从系统环境变量中读取
            for k, v in shell_env.items():
                if not v:
                    env_val = os.environ.get(k, '')
                    if env_val:
                        shell_env[k] = env_val

            return BotSettingsResponse(
                bot_id=str(bot_id),
                name=bot_name,
                model_id=model_id,
                model=model_info,
                models=models_list,
                language=settings.get('language', 'zh'),
                avatar_url=settings.get('avatar_url'),
                description=settings.get('description'),
                suggestions=settings.get('suggestions'),
                dataset_ids=dataset_ids,
                system_prompt=settings.get('system_prompt'),
                enable_memori=settings.get('enable_memori', False),
                enable_thinking=settings.get('enable_thinking', False),
                tool_response=settings.get('tool_response', False),
                skills=skills_list,
                shell_env=shell_env,
                is_published=is_published if is_published else False,
                is_owner=is_owner,
                copied_from=str(copied_from) if copied_from else None,
                voice_speaker=settings.get('voice_speaker'),
                voice_system_role=settings.get('voice_system_role'),
                voice_speaking_style=settings.get('voice_speaking_style'),
                updated_at=datetime_to_str(updated_at)
            )


@router.put("/api/v1/bots/{bot_uuid}/settings", response_model=SuccessResponse)
async def update_bot_settings(
    bot_uuid: str,
    request: BotSettingsUpdate,
    authorization: Optional[str] = Header(None)
):
    """
    更新 Bot 设置（仅所有者和 editor 可以更新）

    Args:
        bot_uuid: Bot 内部 UUID
        request: 设置更新请求
        authorization: Bearer token

    Returns:
        SuccessResponse: 更新结果
    """
    user_valid, user_id, user_username = await verify_user_auth(authorization)

    if not user_valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    # 检查是否是管理员
    is_admin = await is_admin_user(authorization)

    # 用户需要检查是否有 write 权限
    if not is_admin:
        if not await check_bot_access(bot_uuid, user_id, 'write'):
            raise HTTPException(
                status_code=403,
                detail="You don't have permission to modify this bot"
            )

    pool = get_db_pool_manager().pool

    # 处理 model_id：将空字符串转换为 None
    model_id_value = request.model_id.strip() if request.model_id else None

    # 注意：model_id 现在来自 New API，不再在本地 agent_models 表中验证

    # 构建 JSONB 更新对象
    update_json = {}
    if request.model_id is not None:
        update_json['model_id'] = model_id_value if model_id_value else None
    if request.language is not None:
        update_json['language'] = request.language
    if request.avatar_url is not None:
        update_json['avatar_url'] = request.avatar_url
    if request.description is not None:
        update_json['description'] = request.description
    if request.suggestions is not None:
        update_json['suggestions'] = request.suggestions
    if request.dataset_ids is not None:
        # 将数组转换为逗号分隔的字符串存储
        update_json['dataset_ids'] = ','.join(request.dataset_ids) if request.dataset_ids else None
    if request.system_prompt is not None:
        update_json['system_prompt'] = request.system_prompt
    if request.enable_memori is not None:
        update_json['enable_memori'] = request.enable_memori
    if request.enable_thinking is not None:
        update_json['enable_thinking'] = request.enable_thinking
    if request.tool_response is not None:
        update_json['tool_response'] = request.tool_response
    if request.skills is not None:
        update_json['skills'] = request.skills
    if request.shell_env is not None:
        update_json['shell_env'] = request.shell_env
    if request.voice_speaker is not None:
        update_json['voice_speaker'] = request.voice_speaker
    if request.voice_system_role is not None:
        update_json['voice_system_role'] = request.voice_system_role
    if request.voice_speaking_style is not None:
        update_json['voice_speaking_style'] = request.voice_speaking_style

    # is_published 是表字段，不在 settings JSON 中
    need_update_published = request.is_published is not None

    if not update_json and not need_update_published:
        raise HTTPException(status_code=400, detail="No fields to update")

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("SELECT id, settings FROM agent_bots WHERE id = %s", (bot_uuid,))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(status_code=404, detail="Bot not found")

            # 合并现有设置和新设置
            existing_settings = row[1] if row[1] else {}
            existing_settings.update(update_json)

            # 更新设置和is_published字段
            if need_update_published:
                await cursor.execute("""
                    UPDATE agent_bots
                    SET settings = %s, is_published = %s, updated_at = NOW()
                    WHERE id = %s
                """, (json.dumps(existing_settings), request.is_published, bot_uuid))
            else:
                await cursor.execute("""
                    UPDATE agent_bots
                    SET settings = %s, updated_at = NOW()
                    WHERE id = %s
                """, (json.dumps(existing_settings), bot_uuid))

            await conn.commit()

            # 同步更新所有从此智能体复制的智能体
            # 查找所有 copied_from 等于当前 bot_uuid 的智能体
            await cursor.execute("""
                SELECT id, settings
                FROM agent_bots
                WHERE copied_from = %s
            """, (bot_uuid,))
            copied_bots = await cursor.fetchall()

            for copied_bot in copied_bots:
                copied_bot_id, copied_settings = copied_bot
                copied_settings = copied_settings if copied_settings else {}

                # 同步配置：系统提示词、skill、AI模型、语言、交互设置
                copied_settings['system_prompt'] = existing_settings.get('system_prompt')
                copied_settings['skills'] = existing_settings.get('skills')
                copied_settings['model_id'] = existing_settings.get('model_id')
                copied_settings['language'] = existing_settings.get('language')
                copied_settings['tool_response'] = existing_settings.get('tool_response')
                copied_settings['enable_thinking'] = existing_settings.get('enable_thinking')
                copied_settings['enable_memori'] = existing_settings.get('enable_memori')

                # 更新复制的智能体的设置
                await cursor.execute("""
                    UPDATE agent_bots
                    SET settings = %s, updated_at = NOW()
                    WHERE id = %s
                """, (json.dumps(copied_settings), copied_bot_id))

                # 同步 MCP 服务器配置
                await cursor.execute("""
                    DELETE FROM agent_mcp_servers WHERE bot_id = %s
                """, (copied_bot_id,))

                await cursor.execute("""
                    SELECT name, type, config, enabled
                    FROM agent_mcp_servers
                    WHERE bot_id = %s
                """, (bot_uuid,))
                source_mcp_servers = await cursor.fetchall()

                for server in source_mcp_servers:
                    server_name, server_type, server_config, server_enabled = server
                    await cursor.execute("""
                        INSERT INTO agent_mcp_servers (bot_id, name, type, config, enabled)
                        VALUES (%s, %s, %s, %s, %s)
                    """, (copied_bot_id, server_name, server_type, json.dumps(server_config) if server_config else None, server_enabled))

            # 提交所有同步更新
            if copied_bots:
                await conn.commit()

            # 同步 skills 文件夹到所有复制的智能体
            for copied_bot in copied_bots:
                copied_bot_id = copied_bot[0]
                copy_skills_folder(bot_uuid, str(copied_bot_id))

            return SuccessResponse(success=True, message="Bot settings updated successfully")


# ============== 会话管理 API ==============

@router.get("/api/v1/bots/{bot_uuid}/sessions", response_model=List[SessionResponse])
async def get_bot_sessions(bot_uuid: str, authorization: Optional[str] = Header(None)):
    """
    获取 Bot 的会话列表

    Args:
        bot_uuid: Bot 内部 UUID
        authorization: Bearer token

    Returns:
        List[SessionResponse]: 会话列表
    """
    verify_auth(authorization)

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT id, bot_id, title, created_at, updated_at
                FROM agent_chat_sessions
                WHERE bot_id = %s
                ORDER BY updated_at DESC
            """, (bot_uuid,))
            rows = await cursor.fetchall()

            return [
                SessionResponse(
                    id=str(row[0]),
                    bot_id=str(row[1]),
                    title=row[2],
                    created_at=datetime_to_str(row[3]),
                    updated_at=datetime_to_str(row[4])
                )
                for row in rows
            ]


@router.post("/api/v1/bots/{bot_uuid}/sessions", response_model=SessionResponse)
async def create_session(
    bot_uuid: str,
    request: SessionCreate,
    authorization: Optional[str] = Header(None)
):
    """
    创建新会话

    Args:
        bot_uuid: Bot 内部 UUID
        request: 会话创建请求
        authorization: Bearer token

    Returns:
        SessionResponse: 创建的会话信息
    """
    verify_auth(authorization)

    pool = get_db_pool_manager().pool

    # 验证 Bot 是否存在
    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("SELECT id FROM agent_bots WHERE id = %s", (bot_uuid,))
            if not await cursor.fetchone():
                raise HTTPException(status_code=404, detail="Bot not found")

            # 创建会话
            await cursor.execute("""
                INSERT INTO agent_chat_sessions (bot_id, title)
                VALUES (%s, %s)
                RETURNING id, created_at, updated_at
            """, (bot_uuid, request.title))
            row = await cursor.fetchone()

            await conn.commit()

            return SessionResponse(
                id=str(row[0]),
                bot_id=bot_uuid,
                title=request.title,
                created_at=datetime_to_str(row[1]),
                updated_at=datetime_to_str(row[2])
            )


@router.delete("/api/v1/sessions/{session_id}", response_model=SuccessResponse)
async def delete_session(session_id: str, authorization: Optional[str] = Header(None)):
    """
    删除会话

    Args:
        session_id: 会话 ID
        authorization: Bearer token

    Returns:
        SuccessResponse: 删除结果
    """
    verify_auth(authorization)

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("DELETE FROM agent_chat_sessions WHERE id = %s RETURNING id", (session_id,))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(status_code=404, detail="Session not found")

            await conn.commit()

            return SuccessResponse(success=True, message="Session deleted successfully")


# ============== MCP 服务器 API ==============

@router.get("/api/v1/bots/{bot_uuid}/mcp", response_model=List[MCPServerResponse])
async def get_mcp_servers(bot_uuid: str, authorization: Optional[str] = Header(None)):
    """
    获取 Bot 的 MCP 服务器配置

    Args:
        bot_uuid: Bot 内部 UUID
        authorization: Bearer token

    Returns:
        List[MCPServerResponse]: MCP 服务器列表
    """
    verify_auth(authorization)

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT id, bot_id, name, type, config, enabled, created_at, updated_at
                FROM agent_mcp_servers
                WHERE bot_id = %s
                ORDER BY created_at DESC
            """, (bot_uuid,))
            rows = await cursor.fetchall()

            return [
                MCPServerResponse(
                    id=str(row[0]),
                    bot_id=str(row[1]),
                    name=row[2],
                    type=row[3],
                    config=row[4],
                    enabled=row[5],
                    created_at=datetime_to_str(row[6]),
                    updated_at=datetime_to_str(row[7])
                )
                for row in rows
            ]


@router.put("/api/v1/bots/{bot_uuid}/mcp", response_model=SuccessResponse)
async def update_mcp_servers(
    bot_uuid: str,
    servers: List[MCPServerCreate],
    authorization: Optional[str] = Header(None)
):
    """
    更新 Bot 的 MCP 服务器配置

    Args:
        bot_uuid: Bot 内部 UUID
        servers: MCP 服务器列表
        authorization: Bearer token

    Returns:
        SuccessResponse: 更新结果
    """
    verify_auth(authorization)

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 删除旧的 MCP 配置
            await cursor.execute("DELETE FROM agent_mcp_servers WHERE bot_id = %s", (bot_uuid,))

            # 插入新的 MCP 配置
            for server in servers:
                await cursor.execute("""
                    INSERT INTO agent_mcp_servers (bot_id, name, type, config, enabled)
                    VALUES (%s, %s, %s, %s, %s)
                """, (
                    bot_uuid,
                    server.name,
                    server.type,
                    server.config,
                    server.enabled
                ))

            await conn.commit()

            return SuccessResponse(
                success=True,
                message=f"MCP servers updated successfully ({len(servers)} servers)"
            )


@router.post("/api/v1/bots/{bot_uuid}/mcp", response_model=MCPServerResponse)
async def add_mcp_server(
    bot_uuid: str,
    request: MCPServerCreate,
    authorization: Optional[str] = Header(None)
):
    """
    添加单个 MCP 服务器

    Args:
        bot_uuid: Bot 内部 UUID
        request: MCP 服务器创建请求
        authorization: Bearer token

    Returns:
        MCPServerResponse: 创建的 MCP 服务器信息
    """
    verify_auth(authorization)

    pool = get_db_pool_manager().pool

    # 验证 Bot 是否存在
    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("SELECT id FROM agent_bots WHERE id = %s", (bot_uuid,))
            if not await cursor.fetchone():
                raise HTTPException(status_code=404, detail="Bot not found")

            # 创建 MCP 服务器
            await cursor.execute("""
                INSERT INTO agent_mcp_servers (bot_id, name, type, config, enabled)
                VALUES (%s, %s, %s, %s, %s)
                RETURNING id, created_at, updated_at
            """, (
                bot_uuid,
                request.name,
                request.type,
                request.config,
                request.enabled
            ))
            row = await cursor.fetchone()

            await conn.commit()

            return MCPServerResponse(
                id=str(row[0]),
                bot_id=bot_uuid,
                name=request.name,
                type=request.type,
                config=request.config,
                enabled=request.enabled,
                created_at=datetime_to_str(row[1]),
                updated_at=datetime_to_str(row[2])
            )


@router.delete("/api/v1/bots/{bot_uuid}/mcp/{mcp_id}", response_model=SuccessResponse)
async def delete_mcp_server(
    bot_uuid: str,
    mcp_id: str,
    authorization: Optional[str] = Header(None)
):
    """
    删除 MCP 服务器

    Args:
        bot_uuid: Bot 内部 UUID
        mcp_id: MCP 服务器 ID
        authorization: Bearer token

    Returns:
        SuccessResponse: 删除结果
    """
    verify_auth(authorization)

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute(
                "DELETE FROM agent_mcp_servers WHERE id = %s AND bot_id = %s RETURNING id",
                (mcp_id, bot_uuid)
            )
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(status_code=404, detail="MCP server not found")

            await conn.commit()

            return SuccessResponse(success=True, message="MCP server deleted successfully")


# ============== Admin 登录 API ==============

@router.post("/api/v1/admin/login", response_model=AdminLoginResponse)
async def admin_login(request: AdminLoginRequest):
    """
    管理员登录

    Args:
        request: 登录请求（用户名和密码）

    Returns:
        AdminLoginResponse: 登录成功返回 token
    """
    # 硬编码验证账号密码
    if request.username != ADMIN_USERNAME or request.password != ADMIN_PASSWORD:
        raise HTTPException(
            status_code=401,
            detail="用户名或密码错误"
        )

    pool = get_db_pool_manager().pool

    # 生成 token
    token = secrets.token_urlsafe(32)
    expires_at = datetime.now() + timedelta(hours=TOKEN_EXPIRE_HOURS)

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 清理该用户的旧 token
            await cursor.execute("DELETE FROM agent_admin_tokens WHERE username = %s", (request.username,))

            # 保存新 token
            await cursor.execute("""
                INSERT INTO agent_admin_tokens (username, token, expires_at)
                VALUES (%s, %s, %s)
            """, (request.username, token, expires_at))

            await conn.commit()

    return AdminLoginResponse(
        token=token,
        username=request.username,
        expires_at=expires_at.isoformat()
    )


@router.post("/api/v1/admin/verify", response_model=AdminVerifyResponse)
async def admin_verify(authorization: Optional[str] = Header(None)):
    """
    验证管理员 token 是否有效

    Args:
        authorization: Bearer token

    Returns:
        AdminVerifyResponse: 验证结果
    """
    is_admin = await is_admin_user(authorization)
    user_valid, _, username = await verify_user_auth(authorization)

    return AdminVerifyResponse(
        valid=is_admin,
        username=username if is_admin else None
    )


@router.post("/api/v1/admin/logout", response_model=SuccessResponse)
async def admin_logout(authorization: Optional[str] = Header(None)):
    """
    管理员登出（删除 token）

    Args:
        authorization: Bearer token

    Returns:
        SuccessResponse: 登出结果
    """
    provided_token = extract_api_key_from_auth(authorization)
    if not provided_token:
        raise HTTPException(
            status_code=401,
            detail="Authorization header is required"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("DELETE FROM agent_admin_tokens WHERE token = %s", (provided_token,))
            await conn.commit()

    return SuccessResponse(success=True, message="Logged out successfully")


# ============== 用户认证 API ==============

@router.post("/api/v1/auth/register", response_model=UserLoginResponse)
async def user_register(request: UserRegisterRequest):
    """
    用户注册（需��邀请码）

    Args:
        request: 注册请求（用户名、邮箱、密码、邀请码）

    Returns:
        UserLoginResponse: 注册成功返回 token 和用户信息
    """
    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 1. 验证邀请码（固定邀请码）
            if request.invitation_code != "WELCOME2026":
                raise HTTPException(
                    status_code=400,
                    detail="邀请码无效"
                )

            # 2. 检查用户名是否已存在
            await cursor.execute("""
                SELECT id FROM agent_user WHERE username = %s
            """, (request.username,))
            if await cursor.fetchone():
                raise HTTPException(
                    status_code=400,
                    detail="用户名已存在"
                )

            # 3. 检查邮箱是否已存在（如果提供）
            if request.email:
                await cursor.execute("""
                    SELECT id FROM agent_user WHERE email = %s
                """, (request.email,))
                if await cursor.fetchone():
                    raise HTTPException(
                        status_code=400,
                        detail="邮箱已被注册"
                    )

            # 4. 创建用户
            password_hash = hash_password(request.password)
            await cursor.execute("""
                INSERT INTO agent_user (username, email, password_hash)
                VALUES (%s, %s, %s)
                RETURNING id, created_at
            """, (request.username, request.email, password_hash))
            user_id, created_at = await cursor.fetchone()

            # 5. 同步注册到 New API（静默失败）
            new_api_session = None
            new_api_user_id = None
            try:
                proxy = get_new_api_proxy()
                # 使用假邮箱或提供的邮箱注册
                register_email = request.email or f"{request.username}@fake.local"
                register_result = await proxy.register(request.username, request.password, register_email)
                logger.info(f"New API register result for {request.username}: success={register_result.get('success')}, message={register_result.get('message', 'N/A')}")

                if register_result.get("success"):
                    # 注册成功后立即登录获取 session 和 user_id
                    login_result = await proxy.login(request.username, request.password)
                    if login_result.get("success"):
                        new_api_session = login_result.get("session")
                        new_api_user_id = login_result.get("data", {}).get("id")
                        await cursor.execute("""
                            UPDATE agent_user
                            SET new_api_session = %s, new_api_user_id = %s
                            WHERE id = %s
                        """, (new_api_session, new_api_user_id, user_id))
                        logger.info(f"New API session and user_id stored for user {request.username}")
                else:
                    # 如果注册失败（可能用户已存在），尝试直接登录
                    logger.warning(f"New API register failed, trying login: {register_result.get('message')}")
                    login_result = await proxy.login(request.username, request.password)
                    if login_result.get("success"):
                        new_api_session = login_result.get("session")
                        new_api_user_id = login_result.get("data", {}).get("id")
                        await cursor.execute("""
                            UPDATE agent_user
                            SET new_api_session = %s, new_api_user_id = %s
                            WHERE id = %s
                        """, (new_api_session, new_api_user_id, user_id))
                        logger.info(f"New API session and user_id stored for user {request.username} via login")
            except Exception as e:
                logger.warning(f"New API sync failed for user {request.username}: {e}")

            # 6. 生成 token
            token = secrets.token_urlsafe(32)
            expires_at = datetime.now() + timedelta(hours=TOKEN_EXPIRE_HOURS)

            await cursor.execute("""
                INSERT INTO agent_user_tokens (user_id, token, expires_at)
                VALUES (%s, %s, %s)
            """, (user_id, token, expires_at))

            await conn.commit()

            return UserLoginResponse(
                token=token,
                user_id=str(user_id),
                username=request.username,
                email=request.email,
                is_admin=False,
                expires_at=expires_at.isoformat()
            )


@router.post("/api/v1/auth/login", response_model=UserLoginResponse)
async def user_login(request: UserLoginRequest):
    """
    用户登录

    Args:
        request: 登录请求（用户名、密码）

    Returns:
        UserLoginResponse: 登录成功返回 token 和用户信息
    """
    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 1. 验证用户名和密码
            password_hash = hash_password(request.password)
            await cursor.execute("""
                SELECT id, username, email, is_active, is_admin, is_subaccount, parent_id
                FROM agent_user
                WHERE username = %s AND password_hash = %s
            """, (request.username, password_hash))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=401,
                    detail="用户名或密码错误"
                )

            user_id, username, email, is_active, is_admin, is_subaccount, parent_id = row

            if not is_active:
                raise HTTPException(
                    status_code=403,
                    detail="账户已被禁用"
                )

            # 2. 更新最后登录时间
            await cursor.execute("""
                UPDATE agent_user
                SET last_login = NOW()
                WHERE id = %s
            """, (user_id,))

            # 3. 清理旧 token
            await cursor.execute("""
                DELETE FROM agent_user_tokens
                WHERE user_id = %s
            """, (user_id,))

            # 4. 生成新 token
            token = secrets.token_urlsafe(32)
            expires_at = datetime.now() + timedelta(hours=TOKEN_EXPIRE_HOURS)

            await cursor.execute("""
                INSERT INTO agent_user_tokens (user_id, token, expires_at)
                VALUES (%s, %s, %s)
            """, (user_id, token, expires_at))

            # 5. 尝试同步 New API session 和令牌（静默失败）
            new_api_session = None
            new_api_user_id = None
            new_api_token = None
            try:
                proxy = get_new_api_proxy()
                # 使用 username 登录 New API
                logger.info(f"Attempting New API login for user {username}")
                login_result = await proxy.login(request.username, request.password)
                logger.info(f"New API login result: success={login_result.get('success')}, message={login_result.get('message', 'N/A')}")

                if login_result.get("success"):
                    logger.info(f"New API login successful for user {username}")
                    # 存储 session 和 user_id
                    new_api_session = login_result.get("session")
                    new_api_user_id = login_result.get("data", {}).get("id")
                    if new_api_session or new_api_user_id:
                        # 获取或创建令牌
                        cookies = {"session": new_api_session} if new_api_session else {}
                        token_result = await proxy.get_or_create_token(cookies, new_api_user_id)
                        if token_result.get("success") and token_result.get("data"):
                            new_api_token = token_result["data"].get("key")
                            logger.info(f"Got New API token for user {username}")

                        await cursor.execute("""
                            UPDATE agent_user
                            SET new_api_session = %s, new_api_user_id = %s, new_api_token = %s
                            WHERE id = %s
                        """, (new_api_session, new_api_user_id, new_api_token, user_id))
                        logger.info(f"Stored New API session, user_id and token for user {username} token: {new_api_token}")
                    else:
                        logger.warning(f"New API login succeeded but no session/user_id. Response: {login_result}")
                else:
                    # 登录失败，尝试先注册再登录（可能是用户在 New API 不存在）
                    logger.info(f"New API login failed, trying to register user {username}")
                    register_email = email or f"{request.username}@fake.local"
                    register_result = await proxy.register(request.username, request.password, register_email)
                    logger.info(f"New API register result: success={register_result.get('success')}, message={register_result.get('message', 'N/A')}")

                    if register_result.get("success"):
                        # 注册成功后再次登录
                        login_result = await proxy.login(request.username, request.password)
                        if login_result.get("success"):
                            new_api_session = login_result.get("session")
                            new_api_user_id = login_result.get("data", {}).get("id")
                            # 获取或创建令牌
                            cookies = {"session": new_api_session} if new_api_session else {}
                            token_result = await proxy.get_or_create_token(cookies, new_api_user_id)
                            if token_result.get("success") and token_result.get("data"):
                                new_api_token = token_result["data"].get("key")
                                logger.info(f"Got New API token for user {username} after registration")
                            await cursor.execute("""
                                UPDATE agent_user
                                SET new_api_session = %s, new_api_user_id = %s, new_api_token = %s
                                WHERE id = %s
                            """, (new_api_session, new_api_user_id, new_api_token, user_id))
                            logger.info(f"New API session, user_id and token stored for user {username} after registration")
                    else:
                        logger.warning(f"New API register also failed for user {username}: {register_result.get('message')}")
            except Exception as e:
                # 静默失败，不影响本地登录
                logger.warning(f"New API login sync failed for user {username}: {e}")

            await conn.commit()

            # 获取单智能体配置
            single_agent_config = await get_or_create_single_agent_bot(str(user_id), pool)

            return UserLoginResponse(
                token=token,
                user_id=str(user_id),
                username=username,
                email=email,
                is_admin=is_admin or False,
                is_subaccount=is_subaccount or False,
                parent_id=str(parent_id) if parent_id else None,
                expires_at=expires_at.isoformat(),
                single_agent=single_agent_config
            )


@router.post("/api/v1/auth/verify", response_model=UserVerifyResponse)
async def user_verify(authorization: Optional[str] = Header(None)):
    """
    验证用户 token 是否有效

    Args:
        authorization: Bearer token

    Returns:
        UserVerifyResponse: 验证结果
    """
    valid, user_id, username = await verify_user_auth(authorization)

    is_admin_flag = False
    is_subaccount_flag = False
    if valid and user_id:
        pool = get_db_pool_manager().pool
        async with pool.connection() as conn:
            async with conn.cursor() as cursor:
                await cursor.execute("""
                    SELECT is_admin, is_subaccount FROM agent_user WHERE id = %s
                """, (user_id,))
                row = await cursor.fetchone()
                if row:
                    is_admin_flag = row[0] or False
                    is_subaccount_flag = row[1] or False

    return UserVerifyResponse(
        valid=valid,
        user_id=user_id,
        username=username,
        is_admin=is_admin_flag,
        is_subaccount=is_subaccount_flag
    )


@router.get("/api/v1/users/me", response_model=UserInfoResponse)
async def get_current_user(authorization: Optional[str] = Header(None)):
    """
    获取当前用户信息

    Args:
        authorization: Bearer token

    Returns:
        UserInfoResponse: 用户信息
    """
    valid, user_id, username = await verify_user_auth(authorization)

    if not valid:
        raise HTTPException(
            status_code=401,
            detail="Invalid token"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT id, username, email, is_admin, is_subaccount, parent_id, created_at, last_login
                FROM agent_user
                WHERE id = %s
            """, (user_id,))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=404,
                    detail="User not found"
                )

            user_id, username, email, is_admin, is_subaccount, parent_id, created_at, last_login = row

            return UserInfoResponse(
                id=str(user_id),
                username=username,
                email=email,
                is_admin=is_admin or False,
                is_subaccount=is_subaccount or False,
                parent_id=str(parent_id) if parent_id else None,
                created_at=created_at.isoformat() if created_at else "",
                last_login=last_login.isoformat() if last_login else None
            )


@router.patch("/api/v1/users/me", response_model=UserInfoResponse)
async def update_current_user(
    request: UserProfileUpdateRequest,
    authorization: Optional[str] = Header(None)
):
    """
    更新当前用户信息

    Args:
        request: 更新请求（username 或 email）
        authorization: Bearer token

    Returns:
        UserInfoResponse: 更新后的用户信息
    """
    valid, user_id, current_username = await verify_user_auth(authorization)

    if not valid:
        raise HTTPException(
            status_code=401,
            detail="Invalid token"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 构建更新字段
            update_fields = []
            values = []

            if request.username is not None:
                # 检查用户名是否已被其他用户使用
                await cursor.execute("""
                    SELECT id FROM agent_user WHERE username = %s AND id != %s
                """, (request.username, user_id))
                if await cursor.fetchone():
                    raise HTTPException(
                        status_code=400,
                        detail="用户名已存在"
                    )
                update_fields.append("username = %s")
                values.append(request.username)

            if request.email is not None:
                # 检查邮箱是否已被其他用户使用
                await cursor.execute("""
                    SELECT id FROM agent_user WHERE email = %s AND id != %s
                """, (request.email, user_id))
                if await cursor.fetchone():
                    raise HTTPException(
                        status_code=400,
                        detail="邮箱已被使用"
                    )
                update_fields.append("email = %s")
                values.append(request.email)

            if not update_fields:
                raise HTTPException(
                    status_code=400,
                    detail="No fields to update"
                )

            update_fields.append("updated_at = NOW()")
            values.append(user_id)

            await cursor.execute(f"""
                UPDATE agent_user
                SET {', '.join(update_fields)}
                WHERE id = %s
                RETURNING id, username, email, is_admin, created_at, last_login
            """, values)
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=404,
                    detail="User not found"
                )

            await conn.commit()

            return UserInfoResponse(
                id=str(row[0]),
                username=row[1],
                email=row[2],
                is_admin=row[3] or False,
                created_at=row[4].isoformat() if row[4] else "",
                last_login=row[5].isoformat() if row[5] else None
            )


@router.post("/api/v1/users/me/change-password", response_model=SuccessResponse)
async def change_current_user_password(
    request: ChangePasswordRequest,
    authorization: Optional[str] = Header(None)
):
    """
    修改当前用户密码

    Args:
        request: 修改密码请求（old_password, new_password）
        authorization: Bearer token

    Returns:
        SuccessResponse: 操作结果
    """
    valid, user_id, _ = await verify_user_auth(authorization)

    if not valid:
        raise HTTPException(
            status_code=401,
            detail="Invalid token"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 验证旧密码
            old_password_hash = hash_password(request.old_password)

            await cursor.execute("""
                SELECT id FROM agent_user WHERE id = %s AND password_hash = %s
            """, (user_id, old_password_hash))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=400,
                    detail="原密码错误"
                )

            # 更新新密码
            new_password_hash = hash_password(request.new_password)

            await cursor.execute("""
                UPDATE agent_user
                SET password_hash = %s,
                    updated_at = NOW()
                WHERE id = %s
                RETURNING username
            """, (new_password_hash, user_id))
            user_row = await cursor.fetchone()

            await conn.commit()

            return SuccessResponse(
                success=True,
                message="密码修改成功"
            )


@router.get("/api/v1/users", response_model=List[UserSearchResponse])
async def search_users(
    q: str = "",
    authorization: Optional[str] = Header(None)
):
    """
    搜索用户（用于分享）

    Args:
        q: 搜索关键词（用户名或邮箱）
        authorization: Bearer token

    Returns:
        List[UserSearchResponse]: 用户列表
    """
    user_valid, user_id, _ = await verify_user_auth(authorization)

    if not user_valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    if not q:
        return []

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 动态构建查询：如果有 user_id 则排除当前用户
            if user_id:
                await cursor.execute("""
                    SELECT id, username, email
                    FROM agent_user
                    WHERE is_active = TRUE
                    AND (username ILIKE %s OR email ILIKE %s)
                    AND id != %s
                    ORDER BY username
                    LIMIT 20
                """, (f"%{q}%", f"%{q}%", user_id))
            else:
                await cursor.execute("""
                    SELECT id, username, email
                    FROM agent_user
                    WHERE is_active = TRUE
                    AND (username ILIKE %s OR email ILIKE %s)
                    ORDER BY username
                    LIMIT 20
                """, (f"%{q}%", f"%{q}%"))
            rows = await cursor.fetchall()

            return [
                UserSearchResponse(
                    id=str(row[0]),
                    username=row[1],
                    email=row[2]
                )
                for row in rows
            ]


# ============== 用户管理 API（仅管理员）=============

class UserListResponse(BaseModel):
    """用户列表响应"""
    id: str
    username: str
    email: Optional[str] = None
    is_admin: bool = False
    is_active: bool = True
    created_at: str
    last_login: Optional[str] = None
    parent_id: Optional[str] = None
    is_subaccount: bool = False
    subaccount_count: int = 0


class UserCreateRequest(BaseModel):
    """创建用户请求"""
    email: str
    username: Optional[str] = None
    password: str
    is_admin: bool = False


class UserUpdateRequest(BaseModel):
    """更新用户请求"""
    email: Optional[str] = None
    username: Optional[str] = None


class ResetPasswordRequest(BaseModel):
    """重置密码请求"""
    new_password: str


@router.get("/api/v1/users/list", response_model=List[UserListResponse])
async def get_all_users(authorization: Optional[str] = Header(None)):
    """
    获取所有用户列表（��管理员）

    Args:
        authorization: Bearer token

    Returns:
        List[UserListResponse]: 用户列表
    """
    if not await is_admin_user(authorization):
        raise HTTPException(
            status_code=403,
            detail="Admin access required"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT
                    u.id, u.username, u.email, u.is_admin, u.is_active,
                    u.created_at, u.last_login, u.parent_id,
                    COALESCE(u.is_subaccount, FALSE),
                    (SELECT COUNT(*) FROM agent_user sub WHERE sub.parent_id = u.id) as subaccount_count
                FROM agent_user u
                ORDER BY u.created_at DESC
            """)
            rows = await cursor.fetchall()

            return [
                UserListResponse(
                    id=str(row[0]),
                    username=row[1],
                    email=row[2],
                    is_admin=row[3] or False,
                    is_active=row[4],
                    created_at=row[5].isoformat() if row[5] else "",
                    last_login=row[6].isoformat() if row[6] else None,
                    parent_id=str(row[7]) if row[7] else None,
                    is_subaccount=row[8] or False,
                    subaccount_count=row[9] or 0
                )
                for row in rows
            ]


@router.get("/api/v1/users/{user_id}", response_model=UserListResponse)
async def get_user(user_id: str, authorization: Optional[str] = Header(None)):
    """
    获取单个用户信息（仅管理员）

    Args:
        user_id: 用户 ID
        authorization: Bearer token

    Returns:
        UserListResponse: 用户信息
    """
    if not await is_admin_user(authorization):
        raise HTTPException(
            status_code=403,
            detail="Admin access required"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT
                    u.id, u.username, u.email, u.is_admin, u.is_active,
                    u.created_at, u.last_login, u.parent_id,
                    COALESCE(u.is_subaccount, FALSE),
                    (SELECT COUNT(*) FROM agent_user sub WHERE sub.parent_id = u.id) as subaccount_count
                FROM agent_user u
                WHERE u.id = %s
            """, (user_id,))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=404,
                    detail="User not found"
                )

            return UserListResponse(
                id=str(row[0]),
                username=row[1],
                email=row[2],
                is_admin=row[3] or False,
                is_active=row[4],
                created_at=row[5].isoformat() if row[5] else "",
                last_login=row[6].isoformat() if row[6] else None,
                parent_id=str(row[7]) if row[7] else None,
                is_subaccount=row[8] or False,
                subaccount_count=row[9] or 0
            )


@router.post("/api/v1/users", response_model=UserListResponse)
async def create_user(
    request: UserCreateRequest,
    authorization: Optional[str] = Header(None)
):
    """
    创建新用户（仅管理员）

    Args:
        request: 创建用户请求
        authorization: Bearer token

    Returns:
        UserListResponse: 创建的用户信息
    """
    if not await is_admin_user(authorization):
        raise HTTPException(
            status_code=403,
            detail="Admin access required"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 如果提供了用户名，检查是否已存在
            if request.username:
                await cursor.execute("""
                    SELECT id FROM agent_user WHERE username = %s
                """, (request.username,))
                if await cursor.fetchone():
                    raise HTTPException(
                        status_code=400,
                        detail="用户名已存在"
                    )

            # 检查邮箱是否已存在
            await cursor.execute("""
                SELECT id FROM agent_user WHERE email = %s
            """, (request.email,))
            if await cursor.fetchone():
                raise HTTPException(
                    status_code=400,
                    detail="邮箱已被注册"
                )

            # 创建用户
            password_hash = hash_password(request.password)
            username = request.username or request.email.split('@')[0]

            await cursor.execute("""
                INSERT INTO agent_user (username, email, password_hash, is_admin)
                VALUES (%s, %s, %s, %s)
                RETURNING id, created_at
            """, (username, request.email, password_hash, request.is_admin))
            user_id, created_at = await cursor.fetchone()

            await conn.commit()

            return UserListResponse(
                id=str(user_id),
                username=username,
                email=request.email,
                is_admin=request.is_admin,
                is_active=True,
                created_at=created_at.isoformat() if created_at else "",
                last_login=None,
                parent_id=None,
                is_subaccount=False,
                subaccount_count=0
            )


@router.put("/api/v1/users/{user_id}", response_model=UserListResponse)
async def update_user(
    user_id: str,
    request: UserUpdateRequest,
    authorization: Optional[str] = Header(None)
):
    """
    更新用户信息（仅管理员）

    Args:
        user_id: 用户 ID
        request: 更新请求
        authorization: Bearer token

    Returns:
        UserListResponse: 更新后的用户信息
    """
    if not await is_admin_user(authorization):
        raise HTTPException(
            status_code=403,
            detail="Admin access required"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 构建更新字段
            update_fields = []
            values = []

            if request.username is not None:
                # 检查用户名是否已被其他用户使用
                await cursor.execute("""
                    SELECT id FROM agent_user WHERE username = %s AND id != %s
                """, (request.username, user_id))
                if await cursor.fetchone():
                    raise HTTPException(
                        status_code=400,
                        detail="用户名已存在"
                    )
                update_fields.append("username = %s")
                values.append(request.username)

            if request.email is not None:
                # 检查邮箱是否已被其他用户使用
                await cursor.execute("""
                    SELECT id FROM agent_user WHERE email = %s AND id != %s
                """, (request.email, user_id))
                if await cursor.fetchone():
                    raise HTTPException(
                        status_code=400,
                        detail="邮箱已被使用"
                    )
                update_fields.append("email = %s")
                values.append(request.email)

            if not update_fields:
                raise HTTPException(
                    status_code=400,
                    detail="No fields to update"
                )

            update_fields.append("updated_at = NOW()")
            values.append(user_id)

            await cursor.execute(f"""
                UPDATE agent_user
                SET {', '.join(update_fields)}
                WHERE id = %s
                RETURNING id, username, email, is_admin, is_active, created_at, last_login, parent_id, is_subaccount
            """, values)
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=404,
                    detail="User not found"
                )

            # 查询子账号数量
            await cursor.execute("""
                SELECT COUNT(*) FROM agent_user WHERE parent_id = %s
            """, (row[0],))
            subaccount_count = (await cursor.fetchone())[0]

            await conn.commit()

            return UserListResponse(
                id=str(row[0]),
                username=row[1],
                email=row[2],
                is_admin=row[3] or False,
                is_active=row[4],
                created_at=row[5].isoformat() if row[5] else "",
                last_login=row[6].isoformat() if row[6] else None,
                parent_id=str(row[7]) if row[7] else None,
                is_subaccount=row[8] or False,
                subaccount_count=subaccount_count or 0
            )


@router.delete("/api/v1/users/{user_id}", response_model=SuccessResponse)
async def delete_user(user_id: str, authorization: Optional[str] = Header(None)):
    """
    删除用户（仅管理员）

    Args:
        user_id: 用户 ID
        authorization: Bearer token

    Returns:
        SuccessResponse: 删除结果
    """
    if not await is_admin_user(authorization):
        raise HTTPException(
            status_code=403,
            detail="Admin access required"
        )

    # 不允许删除默认 admin 用户
    if user_id == '00000000-0000-0000-0000-000000000001':
        raise HTTPException(
            status_code=400,
            detail="Cannot delete default admin user"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("DELETE FROM agent_user WHERE id = %s RETURNING username", (user_id,))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=404,
                    detail="User not found"
                )

            await conn.commit()

            return SuccessResponse(
                success=True,
                message=f"User '{row[0]}' deleted successfully"
            )


@router.patch("/api/v1/users/{user_id}/toggle-admin", response_model=SuccessResponse)
async def toggle_user_admin(user_id: str, authorization: Optional[str] = Header(None)):
    """
    切换用户管理员状态（仅管理员）

    Args:
        user_id: 用户 ID
        authorization: Bearer token

    Returns:
        SuccessResponse: 操作结果
    """
    if not await is_admin_user(authorization):
        raise HTTPException(
            status_code=403,
            detail="Admin access required"
        )

    # 不允许取消默认 admin 的管理员权限
    if user_id == '00000000-0000-0000-0000-000000000001':
        raise HTTPException(
            status_code=400,
            detail="Cannot modify default admin user"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                UPDATE agent_user
                SET is_admin = NOT is_admin,
                    updated_at = NOW()
                WHERE id = %s
                RETURNING is_admin, username
            """, (user_id,))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=404,
                    detail="User not found"
                )

            new_status, username = row

            await conn.commit()

            return SuccessResponse(
                success=True,
                message=f"User '{username}' is now {'an admin' if new_status else 'a regular user'}"
            )


@router.post("/api/v1/users/{user_id}/reset-password", response_model=SuccessResponse)
async def reset_user_password(
    user_id: str,
    request: ResetPasswordRequest,
    authorization: Optional[str] = Header(None)
):
    """
    重置用户密码（仅管理员）

    Args:
        user_id: 用户 ID
        request: 重置密码请求
        authorization: Bearer token

    Returns:
        SuccessResponse: 操作结果
    """
    if not await is_admin_user(authorization):
        raise HTTPException(
            status_code=403,
            detail="Admin access required"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            password_hash = hash_password(request.new_password)

            await cursor.execute("""
                UPDATE agent_user
                SET password_hash = %s,
                    updated_at = NOW()
                WHERE id = %s
                RETURNING username
            """, (password_hash, user_id))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=404,
                    detail="User not found"
                )

            await conn.commit()

            return SuccessResponse(
                success=True,
                message=f"Password reset for user '{row[0]}'"
            )


@router.post("/api/v1/auth/logout", response_model=SuccessResponse)
async def user_logout(authorization: Optional[str] = Header(None)):
    """
    用户登出（删除 token）

    Args:
        authorization: Bearer token

    Returns:
        SuccessResponse: 登出结果
    """
    provided_token = extract_api_key_from_auth(authorization)
    if not provided_token:
        raise HTTPException(
            status_code=401,
            detail="Authorization header is required"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("DELETE FROM agent_user_tokens WHERE token = %s", (provided_token,))
            await conn.commit()

    return SuccessResponse(success=True, message="Logged out successfully")


# ============== 分享管理 API ==============

@router.get("/api/v1/bots/{bot_uuid}/shares", response_model=BotSharesListResponse)
async def get_bot_shares(
    bot_uuid: str,
    authorization: Optional[str] = Header(None)
):
    """
    获取 Bot 的分享列表

    Args:
        bot_uuid: Bot UUID
        authorization: Bearer token

    Returns:
        BotSharesListResponse: 分享列表
    """
    valid, user_id, _ = await verify_user_auth(authorization)

    if not valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    # 验证用户是 Bot 所有者
    if not await is_bot_owner(bot_uuid, user_id):
        raise HTTPException(
            status_code=403,
            detail="Only bot owner can view shares"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT s.id, s.bot_id, s.user_id, u.username, u.email, s.role, s.shared_at, s.expires_at, su.username
                FROM bot_shares s
                JOIN agent_user u ON s.user_id = u.id
                LEFT JOIN agent_user su ON s.shared_by = su.id
                WHERE s.bot_id = %s
                ORDER BY s.shared_at DESC
            """, (bot_uuid,))
            rows = await cursor.fetchall()

            shares = [
                BotShareResponse(
                    id=str(row[0]),
                    bot_id=str(row[1]),
                    user_id=str(row[2]),
                    username=row[3],
                    email=row[4],
                    role=row[5],
                    shared_at=row[6].isoformat() if row[6] else "",
                    expires_at=row[7].isoformat() if row[7] else None,
                    shared_by=row[8] if row[8] is None else str(row[8])
                )
                for row in rows
            ]

            return BotSharesListResponse(
                bot_id=bot_uuid,
                shares=shares
            )


@router.post("/api/v1/bots/{bot_uuid}/shares", response_model=SuccessResponse)
async def add_bot_share(
    bot_uuid: str,
    request: BotShareCreate,
    authorization: Optional[str] = Header(None)
):
    """
    添加 Bot 分享

    Args:
        bot_uuid: Bot UUID
        request: 分享请求
        authorization: Bearer token

    Returns:
        SuccessResponse: 操作结果
    """
    valid, user_id, _ = await verify_user_auth(authorization)

    if not valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    # 验证用户是 Bot 所有者
    if not await is_bot_owner(bot_uuid, user_id):
        raise HTTPException(
            status_code=403,
            detail="Only bot owner can share"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 验证目标用户存在
            for target_user_id in request.user_ids:
                await cursor.execute("""
                    SELECT id FROM agent_user WHERE id = %s AND is_active = TRUE
                """, (target_user_id,))
                if not await cursor.fetchone():
                    raise HTTPException(
                        status_code=400,
                        detail=f"User {target_user_id} not found"
                    )

            # 添加分享
            added_count = 0
            for target_user_id in request.user_ids:
                try:
                    await cursor.execute("""
                        INSERT INTO bot_shares (bot_id, user_id, shared_by, role, expires_at)
                        VALUES (%s, %s, %s, %s, %s)
                        ON CONFLICT (bot_id, user_id) DO UPDATE SET
                            role = EXCLUDED.role,
                            shared_by = EXCLUDED.shared_by,
                            expires_at = EXCLUDED.expires_at
                    """, (bot_uuid, target_user_id, user_id, request.role, request.expires_at))
                    added_count += 1
                except Exception:
                    pass  # 忽略重复的

            await conn.commit()

            return SuccessResponse(
                success=True,
                message=f"Shared with {added_count} user(s)"
            )


@router.delete("/api/v1/bots/{bot_uuid}/shares/{user_id}", response_model=SuccessResponse)
async def remove_bot_share(
    bot_uuid: str,
    user_id: str,
    authorization: Optional[str] = Header(None)
):
    """
    移除 Bot 分享

    Args:
        bot_uuid: Bot UUID
        user_id: 要移除的用户 ID
        authorization: Bearer token

    Returns:
        SuccessResponse: 操作结果
    """
    valid, current_user_id, _ = await verify_user_auth(authorization)

    if not valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    # 验证用户是 Bot 所有者
    if not await is_bot_owner(bot_uuid, current_user_id):
        raise HTTPException(
            status_code=403,
            detail="Only bot owner can remove shares"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                DELETE FROM bot_shares
                WHERE bot_id = %s AND user_id = %s
                RETURNING id
            """, (bot_uuid, user_id))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=404,
                    detail="Share not found"
                )

            await conn.commit()

            return SuccessResponse(
                success=True,
                message="Share removed successfully"
            )


# ============== 智能体广场 API ==============

@router.get("/api/v1/marketplace/bots", response_model=MarketplaceListResponse)
async def get_marketplace_bots(
    page: int = 1,
    page_size: int = 20,
    search: str = "",
    authorization: Optional[str] = Header(None)
):
    """
    获取广场智能体列表

    Args:
        page: 页码（从1开始）
        page_size: 每页数量
        search: 搜索关键词（名称/描述）
        authorization: Bearer token（可选，用于判断是否已登录）

    Returns:
        MarketplaceListResponse: 广场智能体列表
    """
    # 不强制要求登录，但如果有 token 则验证
    user_valid, _, _ = await verify_user_auth(authorization)

    pool = get_db_pool_manager().pool
    offset = (page - 1) * page_size

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 构建搜索条件
            search_condition = ""
            params = []

            if search:
                search_condition = "AND (b.name ILIKE %s OR b.settings->>'description' ILIKE %s)"
                search_param = f"%{search}%"
                params.extend([search_param, search_param])

            # 获取总数
            count_query = f"""
                SELECT COUNT(*)
                FROM agent_bots b
                WHERE b.is_published = TRUE
                {search_condition}
            """
            await cursor.execute(count_query, params)
            total = (await cursor.fetchone())[0]

            # 获取列表
            list_query = f"""
                SELECT b.id, b.name, b.settings, b.created_at, b.updated_at,
                       u.username as owner_name
                FROM agent_bots b
                LEFT JOIN agent_user u ON b.owner_id = u.id
                WHERE b.is_published = TRUE
                {search_condition}
                ORDER BY b.updated_at DESC
                LIMIT %s OFFSET %s
            """
            params.extend([page_size, offset])
            await cursor.execute(list_query, params)
            rows = await cursor.fetchall()

            bots = []
            for row in rows:
                settings = row[2] if row[2] else {}
                # 计算被复制次数
                await cursor.execute("""
                    SELECT COUNT(*) FROM agent_bots WHERE copied_from = %s
                """, (row[0],))
                copy_count = (await cursor.fetchone())[0]

                bots.append(MarketplaceBotResponse(
                    id=str(row[0]),
                    name=row[1],
                    description=settings.get('description'),
                    avatar_url=settings.get('avatar_url'),
                    owner_name=row[5],
                    suggestions=settings.get('suggestions'),
                    copy_count=copy_count,
                    created_at=datetime_to_str(row[3]),
                    updated_at=datetime_to_str(row[4])
                ))

            return MarketplaceListResponse(bots=bots, total=total)


@router.get("/api/v1/marketplace/bots/{bot_uuid}", response_model=MarketplaceBotResponse)
async def get_marketplace_bot_detail(
    bot_uuid: str,
    authorization: Optional[str] = Header(None)
):
    """
    获取广场智能体详情

    Args:
        bot_uuid: Bot UUID
        authorization: Bearer token（可选）

    Returns:
        MarketplaceBotResponse: 智能体公开信息
    """
    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT b.id, b.name, b.settings, b.created_at, b.updated_at,
                       u.username as owner_name, b.is_published
                FROM agent_bots b
                LEFT JOIN agent_user u ON b.owner_id = u.id
                WHERE b.id = %s
            """, (bot_uuid,))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(status_code=404, detail="Bot not found")

            if not row[6]:  # is_published
                raise HTTPException(status_code=404, detail="Bot not found in marketplace")

            settings = row[2] if row[2] else {}

            # 计算被复制次数
            await cursor.execute("""
                SELECT COUNT(*) FROM agent_bots WHERE copied_from = %s
            """, (bot_uuid,))
            copy_count = (await cursor.fetchone())[0]

            return MarketplaceBotResponse(
                id=str(row[0]),
                name=row[1],
                description=settings.get('description'),
                avatar_url=settings.get('avatar_url'),
                owner_name=row[5],
                suggestions=settings.get('suggestions'),
                copy_count=copy_count,
                created_at=datetime_to_str(row[3]),
                updated_at=datetime_to_str(row[4])
            )


@router.post("/api/v1/marketplace/bots/{bot_uuid}/copy", response_model=BotResponse)
async def copy_marketplace_bot(
    bot_uuid: str,
    authorization: Optional[str] = Header(None)
):
    """
    复制广场智能体到个人管理

    Args:
        bot_uuid: 要复制的 Bot UUID
        authorization: Bearer token

    Returns:
        BotResponse: 新创建的 Bot 信息
    """
    user_valid, user_id, user_username = await verify_user_auth(authorization)

    if not user_valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    pool = get_db_pool_manager().pool

    # 获取用户的主账号ID（如果是子账号，新 bot 归属主账号）
    effective_user_id = await get_parent_user_id(user_id)

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 获取原始 Bot 信息
            await cursor.execute("""
                SELECT id, name, settings, is_published
                FROM agent_bots
                WHERE id = %s AND is_published = TRUE
            """, (bot_uuid,))
            original = await cursor.fetchone()

            if not original:
                raise HTTPException(status_code=404, detail="Bot not found in marketplace")

            original_id, original_name, original_settings, _ = original
            settings = original_settings if original_settings else {}

            # 创建新 Bot（名称加"副本"后缀）
            new_name = f"{original_name} (副本)"
            new_bot_id = str(uuid.uuid4())

            # 复制所有设置（不复制知识库）
            new_settings = {
                'model_id': settings.get('model_id'),
                'language': settings.get('language', 'zh'),
                'avatar_url': settings.get('avatar_url'),
                'description': settings.get('description'),
                'suggestions': settings.get('suggestions'),
                # 不复制知识库
                # 'dataset_ids': settings.get('dataset_ids'),
                'system_prompt': settings.get('system_prompt'),
                'enable_memori': settings.get('enable_memori', False),
                'enable_thinking': settings.get('enable_thinking', False),
                'tool_response': settings.get('tool_response', False),
                'skills': settings.get('skills'),
                'shell_env': {k: '' for k in (settings.get('shell_env') or {})},
            }

            # 插入新 Bot（使用 effective_user_id 作为 owner_id）
            await cursor.execute("""
                INSERT INTO agent_bots (name, bot_id, owner_id, settings, copied_from)
                VALUES (%s, %s, %s, %s, %s)
                RETURNING id, created_at, updated_at
            """, (new_name, new_bot_id, effective_user_id, json.dumps(new_settings), original_id))
            new_row = await cursor.fetchone()
            new_id, created_at, updated_at = new_row

            await conn.commit()

            # 复制 skills 文件夹
            copy_skills_folder(str(original_id), str(new_id))

            return BotResponse(
                id=str(new_id),
                name=new_name,
                bot_id=new_bot_id,
                is_owner=True,
                is_shared=False,
                is_published=False,
                copied_from=str(original_id),
                owner={"id": str(effective_user_id), "username": user_username},
                role=None,
                description=new_settings.get('description'),
                avatar_url=new_settings.get('avatar_url'),
                created_at=datetime_to_str(created_at),
                updated_at=datetime_to_str(updated_at)
            )


@router.patch("/api/v1/bots/{bot_uuid}/publish", response_model=SuccessResponse)
async def toggle_bot_publication(
    bot_uuid: str,
    authorization: Optional[str] = Header(None)
):
    """
    切换智能体发布状态（仅所有者可操作）

    Args:
        bot_uuid: Bot UUID
        authorization: Bearer token

    Returns:
        SuccessResponse: 操作结果
    """
    user_valid, user_id, user_username = await verify_user_auth(authorization)

    if not user_valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    pool = get_db_pool_manager().pool

    # 获取用户的主账号ID（如果是子账号）
    effective_user_id = await get_parent_user_id(user_id)

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 检查是否是所有者（包括子账号的主账号）
            await cursor.execute("""
                SELECT id, is_published FROM agent_bots WHERE id = %s AND owner_id = %s
            """, (bot_uuid, effective_user_id))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=403,
                    detail="Only bot owner can toggle publication status"
                )

            current_status = row[1] if row[1] else False
            new_status = not current_status

            # 更新状态
            await cursor.execute("""
                UPDATE agent_bots
                SET is_published = %s, updated_at = NOW()
                WHERE id = %s
            """, (new_status, bot_uuid))

            await conn.commit()

            action = "发布到" if new_status else "取消发布"
            return SuccessResponse(
                success=True,
                message=f"Bot {action} marketplace successfully"
            )


@router.post("/api/v1/bots/{bot_uuid}/sync-from-source", response_model=SuccessResponse)
async def sync_bot_from_source(
    bot_uuid: str,
    authorization: Optional[str] = Header(None)
):
    """
    从原始智能体同步配置（仅限从广场复制的智能体）

    同步以下配置：
    - 系统提示词
    - MCP 服务器配置
    - 技能配置
    - skills 文件夹

    Args:
        bot_uuid: Bot UUID
        authorization: Bearer token

    Returns:
        SuccessResponse: 操作结果
    """
    user_valid, user_id, user_username = await verify_user_auth(authorization)

    if not user_valid:
        raise HTTPException(
            status_code=401,
            detail="Unauthorized"
        )

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 获取当前 Bot 信息
            await cursor.execute("""
                SELECT id, copied_from, settings, owner_id
                FROM agent_bots
                WHERE id = %s
            """, (bot_uuid,))
            current_bot = await cursor.fetchone()

            if not current_bot:
                raise HTTPException(status_code=404, detail="Bot not found")

            current_id, copied_from, current_settings, owner_id = current_bot

            # 检查是否是从广场复制的
            if not copied_from:
                raise HTTPException(
                    status_code=400,
                    detail="This bot is not copied from marketplace"
                )

            # 检查是否是所有者（子账号使用主账号ID判断）
            effective_user_id = await get_parent_user_id(user_id)
            if str(owner_id) != str(effective_user_id):
                raise HTTPException(
                    status_code=403,
                    detail="Only bot owner can sync from source"
                )

            # 获取原始 Bot 信息
            await cursor.execute("""
                SELECT id, settings
                FROM agent_bots
                WHERE id = %s AND is_published = TRUE
            """, (copied_from,))
            source_bot = await cursor.fetchone()

            if not source_bot:
                raise HTTPException(
                    status_code=404,
                    detail="Source bot not found or not published"
                )

            source_id, source_settings = source_bot
            source_settings = source_settings if source_settings else {}
            current_settings = current_settings if current_settings else {}

            # 同步配置：系统提示词、MCP、skill
            current_settings['system_prompt'] = source_settings.get('system_prompt')
            current_settings['skills'] = source_settings.get('skills')

            # 更新当前 Bot 的设置
            await cursor.execute("""
                UPDATE agent_bots
                SET settings = %s, updated_at = NOW()
                WHERE id = %s
            """, (json.dumps(current_settings), bot_uuid))

            # 同步 MCP 服务器配置
            await cursor.execute("""
                DELETE FROM agent_mcp_servers WHERE bot_id = %s
            """, (bot_uuid,))

            await cursor.execute("""
                SELECT name, type, config, enabled
                FROM agent_mcp_servers
                WHERE bot_id = %s
            """, (copied_from,))
            source_mcp_servers = await cursor.fetchall()

            for server in source_mcp_servers:
                server_name, server_type, server_config, server_enabled = server
                await cursor.execute("""
                    INSERT INTO agent_mcp_servers (bot_id, name, type, config, enabled)
                    VALUES (%s, %s, %s, %s, %s)
                """, (bot_uuid, server_name, server_type, json.dumps(server_config), server_enabled))

            await conn.commit()

            # 复制 skills 文件夹
            copy_skills_folder(str(copied_from), str(bot_uuid))

            return SuccessResponse(
                success=True,
                message="Bot synced from source successfully"
            )


# ============== 子账号管理 API ==============

@router.post("/api/v1/subaccounts", response_model=UserLoginResponse)
async def create_subaccount(
    request: SubAccountCreateRequest,
    authorization: Optional[str] = Header(None)
):
    """
    创建子账号

    要求:
    - 当前用户必须是主账号（is_subaccount = false）
    - 子账号用户名不能与已有用户重复
    - 子账号的 parent_id 指向当前用户

    Args:
        request: 子账号创建请求
        authorization: Bearer token

    Returns:
        UserLoginResponse: 新创建的子账号信息（不含 token）
    """
    # 验证当前用户
    user_valid, user_id, username = await verify_user_auth(authorization)
    if not user_valid:
        raise HTTPException(status_code=401, detail="Unauthorized")

    pool = get_db_pool_manager().pool

    # 检查是否为子账号（子账号不能创建子账号）
    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT is_subaccount FROM agent_user WHERE id = %s
            """, (user_id,))
            row = await cursor.fetchone()
            if row and row[0]:
                raise HTTPException(
                    status_code=403,
                    detail="Subaccounts cannot create subaccounts"
                )

            # 检查用户名是否已存在
            await cursor.execute("""
                SELECT id FROM agent_user WHERE username = %s
            """, (request.username,))
            if await cursor.fetchone():
                raise HTTPException(
                    status_code=400,
                    detail="Username already exists"
                )

            # 检查邮箱是否已存在
            if request.email:
                await cursor.execute("""
                    SELECT id FROM agent_user WHERE email = %s
                """, (request.email,))
                if await cursor.fetchone():
                    raise HTTPException(
                        status_code=400,
                        detail="Email already exists"
                    )

            # 创建子账号
            password_hash = hash_password(request.password)
            await cursor.execute("""
                INSERT INTO agent_user (username, email, password_hash, is_subaccount, parent_id)
                VALUES (%s, %s, %s, %s, %s)
                RETURNING id, username, email, is_admin, is_subaccount, parent_id, created_at
            """, (request.username, request.email, password_hash, True, user_id))
            row = await cursor.fetchone()
            await conn.commit()

            new_user_id, new_username, new_email, is_admin, is_subaccount, parent_id, created_at = row

            return UserLoginResponse(
                token="",  # 不返回 token，需要子账号自己登录
                user_id=str(new_user_id),
                username=new_username,
                email=new_email,
                is_admin=is_admin or False,
                is_subaccount=is_subaccount or False,
                parent_id=str(parent_id) if parent_id else None,
                expires_at=""
            )


@router.get("/api/v1/subaccounts", response_model=List[SubAccountListItem])
async def list_subaccounts(authorization: Optional[str] = Header(None)):
    """
    获取当前主账号的所有子账号列表

    Args:
        authorization: Bearer token

    Returns:
        List[SubAccountListItem]: 子账号列表
    """
    # 验证当前用户
    user_valid, user_id, _ = await verify_user_auth(authorization)
    if not user_valid:
        raise HTTPException(status_code=401, detail="Unauthorized")

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            await cursor.execute("""
                SELECT id, username, email, is_active, created_at, last_login
                FROM agent_user
                WHERE parent_id = %s
                ORDER BY created_at DESC
            """, (user_id,))
            rows = await cursor.fetchall()

            result = []
            for row in rows:
                result.append(SubAccountListItem(
                    id=str(row[0]),
                    username=row[1],
                    email=row[2],
                    is_active=row[3],
                    created_at=row[4].isoformat() if row[4] else "",
                    last_login=row[5].isoformat() if row[5] else None
                ))

            return result


@router.delete("/api/v1/subaccounts/{subaccount_id}")
async def delete_subaccount(
    subaccount_id: str,
    authorization: Optional[str] = Header(None)
):
    """
    删除子账号

    要求:
    - 只能删除属于自己的子账号
    - 主账号不能被此接口删除

    Args:
        subaccount_id: 子账号 UUID
        authorization: Bearer token

    Returns:
        dict: 删除结果
    """
    # 验证当前用户
    user_valid, user_id, _ = await verify_user_auth(authorization)
    if not user_valid:
        raise HTTPException(status_code=401, detail="Unauthorized")

    pool = get_db_pool_manager().pool

    async with pool.connection() as conn:
        async with conn.cursor() as cursor:
            # 验证子账号属于当前用户
            await cursor.execute("""
                SELECT parent_id FROM agent_user WHERE id = %s
            """, (subaccount_id,))
            row = await cursor.fetchone()

            if not row:
                raise HTTPException(
                    status_code=404,
                    detail="Subaccount not found"
                )

            parent_id = row[0]
            if str(parent_id) != user_id:
                raise HTTPException(
                    status_code=403,
                    detail="Subaccount does not belong to you"
                )

            # 删除子账号（级联删除相关的 tokens 等）
            await cursor.execute("""
                DELETE FROM agent_user WHERE id = %s
            """, (subaccount_id,))
            await conn.commit()

            return {"message": "Subaccount deleted successfully"}

