"""
智能体 API
"""
import json
import logging
from typing import List, Optional
from datetime import datetime

from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi.responses import StreamingResponse
from sqlalchemy import select, func, or_, and_
from sqlalchemy.ext.asyncio import AsyncSession

from app.database import get_db
from app.base_schema import PaginatedResponse, ResponseModel
from utils.context import get_current_user_id_from_context
from ai_platform.models import (
    Agent, AgentConversation, AgentMessage,
    LLMModel, AIWorkflow,
)
from core.application.model import Application
from ai_platform.schemas.agent_schema import (
    AgentCreate,
    AgentUpdate,
    AgentResponse,
    AgentListResponse,
    AgentImportCheckIn,
    AgentImportCheckOut,
    AgentImportIn,
    AgentConversationCreate,
    AgentConversationResponse,
    AgentConversationListResponse,
    AgentMessageResponse,
    ChatInput,
    MessageFeedback,
    AgentPublishInput,
)
from ai_platform.services.agent_import_export import (
    AgentImportExportException,
    export_config as export_agent_config,
    check_import as check_agent_import,
    import_config as import_agent_config,
)

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/agent", tags=["AI-智能体"])


# ==================== Agent API ====================

# 资源类型（用于数据权限配置）
AGENT_RESOURCE_TYPE = "ai_agent"
AGENT_RESOURCE_DISPLAY_NAME = "智能体管理"


@router.get("/list", response_model=PaginatedResponse[AgentListResponse], summary="智能体列表")
async def list_agents(
    name: Optional[str] = Query(None, description="名称"),
    mode: Optional[str] = Query(None, description="模式"),
    status: Optional[str] = Query(None, description="状态"),
    application_id: Optional[str] = Query(None, alias="applicationId", description="所属应用ID"),
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(20, ge=1, le=100, alias="pageSize", description="每页数量"),
    db: AsyncSession = Depends(get_db),
):
    """获取智能体列表（自动应用数据权限）"""
    from app.data_scope_utils import get_data_scope_filter, apply_data_scope_to_conditions
    
    conditions = [Agent.is_deleted == False]
    
    if application_id:
        conditions.append(or_(
            Agent.application_id == application_id,
            and_(Agent.application_id.is_(None), Agent.is_global == True)
        ))
    if name:
        conditions.append(Agent.name.ilike(f"%{name}%"))
    if mode:
        conditions.append(Agent.mode == mode)
    if status:
        conditions.append(Agent.status == status)
    
    # 获取数据权限过滤条件并应用
    data_scope_filter = await get_data_scope_filter(db, AGENT_RESOURCE_TYPE)
    scope_conditions = apply_data_scope_to_conditions(Agent, data_scope_filter)
    conditions.extend(scope_conditions)
    
    # 获取总数
    query = select(Agent).where(and_(*conditions))
    count_result = await db.execute(select(func.count()).select_from(query.subquery()))
    total = count_result.scalar() or 0
    
    # 分页
    offset = (page - 1) * page_size
    query = query.order_by(Agent.sort.desc(), Agent.sys_create_datetime.desc())
    query = query.offset(offset).limit(page_size)
    
    result = await db.execute(query)
    agents = result.scalars().all()
    
    # 批量查询应用名称
    app_ids = list({a.application_id for a in agents if a.application_id})
    app_name_map = {}
    if app_ids:
        app_result = await db.execute(
            select(Application.id, Application.name).where(Application.id.in_(app_ids))
        )
        app_name_map = {row.id: row.name for row in app_result}
    
    # 批量查询菜单，判断哪些智能体已发布到菜单
    from core.menu.model import Menu
    agent_codes = [a.code for a in agents if a.code]
    menu_paths = [f"/agent-chat/{code}" for code in agent_codes]
    has_menu_set = set()
    if menu_paths:
        menu_result = await db.execute(
            select(Menu.path).where(
                Menu.path.in_(menu_paths),
                Menu.is_deleted == False
            )
        )
        has_menu_set = {row.path for row in menu_result}
    
    items = []
    for agent in agents:
        model_name = ""
        if agent.model_id:
            model_result = await db.execute(
                select(LLMModel).where(LLMModel.id == agent.model_id)
            )
            model = model_result.scalar_one_or_none()
            model_name = model.display_name if model else ""
        
        has_menu = f"/agent-chat/{agent.code}" in has_menu_set
        items.append(_build_agent_list_response(agent, model_name, app_name_map.get(agent.application_id, ""), has_menu))
    
    return PaginatedResponse(items=items, total=total)


@router.get("/published", response_model=List[AgentListResponse], summary="获取已发布智能体")
async def list_published_agents(db: AsyncSession = Depends(get_db)):
    """获取已发布的智能体列表（用于用户选择）"""
    query = select(Agent).where(
        Agent.is_deleted == False,
        Agent.status == "published"
    ).order_by(Agent.sort.desc())
    
    result = await db.execute(query)
    agents = result.scalars().all()
    
    items = []
    for agent in agents:
        model_name = ""
        if agent.model_id:
            model_result = await db.execute(
                select(LLMModel).where(LLMModel.id == agent.model_id)
            )
            model = model_result.scalar_one_or_none()
            model_name = model.display_name if model else ""
        
        items.append(_build_agent_list_response(agent, model_name))
    
    return items


@router.get("/code/{code}", response_model=AgentResponse, summary="根据编码获取智能体")
async def get_agent_by_code(code: str, db: AsyncSession = Depends(get_db)):
    """根据编码获取智能体"""
    result = await db.execute(
        select(Agent).where(Agent.code == code, Agent.is_deleted == False)
    )
    agent = result.scalar_one_or_none()
    if not agent:
        raise HTTPException(status_code=404, detail="智能体不存在")
    
    return await _build_agent_response(agent, db)


@router.get("/{agent_id}", response_model=AgentResponse, summary="智能体详情")
async def get_agent(agent_id: str, db: AsyncSession = Depends(get_db)):
    """获取智能体详情"""
    result = await db.execute(
        select(Agent).where(Agent.id == agent_id, Agent.is_deleted == False)
    )
    agent = result.scalar_one_or_none()
    if not agent:
        raise HTTPException(status_code=404, detail="智能体不存在")
    
    return await _build_agent_response(agent, db)


@router.post("", response_model=AgentResponse, summary="创建智能体")
async def create_agent(data: AgentCreate, db: AsyncSession = Depends(get_db)):
    """创建智能体"""
    # 检查编码是否重复
    exists_result = await db.execute(
        select(Agent).where(Agent.code == data.code, Agent.is_deleted == False)
    )
    if exists_result.scalar_one_or_none():
        raise HTTPException(status_code=400, detail=f"智能体编码 {data.code} 已存在")
    
    # 验证模型
    if data.model_id:
        model_result = await db.execute(
            select(LLMModel).where(LLMModel.id == data.model_id, LLMModel.is_deleted == False)
        )
        if not model_result.scalar_one_or_none():
            raise HTTPException(status_code=400, detail="模型不存在")
    
    # 验证工作流
    if data.workflow_id:
        workflow_result = await db.execute(
            select(AIWorkflow).where(AIWorkflow.id == data.workflow_id, AIWorkflow.is_deleted == False)
        )
        if not workflow_result.scalar_one_or_none():
            raise HTTPException(status_code=400, detail="工作流不存在")
    
    # 创建智能体
    agent_data = data.model_dump()
    agent = Agent(**agent_data)
    
    # 自动填充创建人和部门
    from utils.context import get_current_user_info_from_context
    user_info = get_current_user_info_from_context()
    if user_info:
        if not agent.sys_creator_id:
            agent.sys_creator_id = user_info.get('user_id')
        if not agent.sys_dept_id and user_info.get('dept_id'):
            agent.sys_dept_id = user_info.get('dept_id')
    
    db.add(agent)
    await db.commit()
    await db.refresh(agent)
    
    return await _build_agent_response(agent, db)


@router.put("/{agent_id}", response_model=AgentResponse, summary="更新智能体")
async def update_agent(
    agent_id: str,
    data: AgentUpdate,
    db: AsyncSession = Depends(get_db),
):
    """更新智能体"""
    result = await db.execute(
        select(Agent).where(Agent.id == agent_id, Agent.is_deleted == False)
    )
    agent = result.scalar_one_or_none()
    if not agent:
        raise HTTPException(status_code=404, detail="智能体不存在")
    
    update_data = data.model_dump(exclude_unset=True)
    
    # 验证模型
    if "model_id" in update_data and update_data["model_id"]:
        model_result = await db.execute(
            select(LLMModel).where(LLMModel.id == update_data["model_id"], LLMModel.is_deleted == False)
        )
        if not model_result.scalar_one_or_none():
            raise HTTPException(status_code=400, detail="模型不存在")
    
    # 验证工作流
    if "workflow_id" in update_data and update_data["workflow_id"]:
        workflow_result = await db.execute(
            select(AIWorkflow).where(AIWorkflow.id == update_data["workflow_id"], AIWorkflow.is_deleted == False)
        )
        if not workflow_result.scalar_one_or_none():
            raise HTTPException(status_code=400, detail="工作流不存在")
    
    for key, value in update_data.items():
        setattr(agent, key, value)
    
    await db.commit()
    await db.refresh(agent)
    
    return await _build_agent_response(agent, db)


@router.delete("/{agent_id}", response_model=ResponseModel, summary="删除智能体")
async def delete_agent(agent_id: str, db: AsyncSession = Depends(get_db)):
    """删除智能体"""
    result = await db.execute(
        select(Agent).where(Agent.id == agent_id, Agent.is_deleted == False)
    )
    agent = result.scalar_one_or_none()
    if not agent:
        raise HTTPException(status_code=404, detail="智能体不存在")
    
    agent.is_deleted = True
    await db.commit()
    
    return ResponseModel(message="删除成功")


@router.get("/{agent_id}/export", summary="导出智能体配置")
async def export_agent(
    agent_id: str,
    db: AsyncSession = Depends(get_db),
):
    """导出智能体配置为 JSON"""
    try:
        config = await export_agent_config(db, agent_id)
        content = json.dumps(config, ensure_ascii=False, indent=2)
        return StreamingResponse(
            iter([content]),
            media_type="application/json",
            headers={
                "Content-Disposition": f'attachment; filename="{config["code"]}.json"'
            },
        )
    except AgentImportExportException as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/import/check", response_model=AgentImportCheckOut, summary="导入预检查")
async def check_import_agent(
    data: AgentImportCheckIn,
    db: AsyncSession = Depends(get_db),
):
    """导入预检查：检查智能体编码是否冲突"""
    try:
        return await check_agent_import(db, data.code)
    except AgentImportExportException as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/import", response_model=AgentResponse, summary="导入智能体配置")
async def import_agent(
    data: AgentImportIn,
    db: AsyncSession = Depends(get_db),
):
    """导入智能体配置"""
    try:
        agent = await import_agent_config(db, data.model_dump())
        await db.commit()
        return await _build_agent_response(agent, db)
    except AgentImportExportException as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/{agent_id}/publish", response_model=AgentResponse, summary="发布智能体")
async def publish_agent(agent_id: str, db: AsyncSession = Depends(get_db)):
    """发布智能体"""
    result = await db.execute(
        select(Agent).where(Agent.id == agent_id, Agent.is_deleted == False)
    )
    agent = result.scalar_one_or_none()
    if not agent:
        raise HTTPException(status_code=404, detail="智能体不存在")
    
    # 验证必要配置
    if agent.mode == "autonomous":
        if not agent.model_id:
            raise HTTPException(status_code=400, detail="请先配置模型")
    elif agent.mode == "dialog_flow":
        if not agent.workflow_id:
            raise HTTPException(status_code=400, detail="对话流模式需要配置工作流")
    
    agent.status = "published"
    await db.commit()
    await db.refresh(agent)
    
    return await _build_agent_response(agent, db)


@router.post("/{agent_id}/disable", response_model=AgentResponse, summary="停用智能体")
async def disable_agent(agent_id: str, db: AsyncSession = Depends(get_db)):
    """停用智能体"""
    result = await db.execute(
        select(Agent).where(Agent.id == agent_id, Agent.is_deleted == False)
    )
    agent = result.scalar_one_or_none()
    if not agent:
        raise HTTPException(status_code=404, detail="智能体不存在")
    
    agent.status = "disabled"
    await db.commit()
    await db.refresh(agent)
    
    return await _build_agent_response(agent, db)


@router.post("/{agent_id}/publish-to-menu", response_model=AgentResponse, summary="发布智能体到菜单")
async def publish_agent_to_menu(
    agent_id: str,
    data: AgentPublishInput,
    db: AsyncSession = Depends(get_db),
):
    """发布智能体到菜单系统"""
    from core.menu.model import Menu
    from core.menu.service import MenuService
    
    # 获取智能体
    result = await db.execute(
        select(Agent).where(Agent.id == agent_id, Agent.is_deleted == False)
    )
    agent = result.scalar_one_or_none()
    if not agent:
        raise HTTPException(status_code=404, detail="智能体不存在")
    
    # 检查智能体是否已发布
    if agent.status != "published":
        raise HTTPException(status_code=400, detail="请先发布智能体")
    
    # 检查是否已存在该智能体的菜单
    menu_path = f"/agent-chat/{agent.code}"
    existing_menu_result = await db.execute(
        select(Menu).where(
            Menu.path == menu_path,
            Menu.is_deleted == False
        )
    )
    existing_menu = existing_menu_result.scalar_one_or_none()
    
    if existing_menu:
        # 更新现有菜单
        existing_menu.name = data.menu_name
        existing_menu.title = data.menu_name
        existing_menu.parent_id = data.menu_parent_id
        existing_menu.icon = data.menu_icon
        existing_menu.order = data.menu_order
        existing_menu.application_id = agent.application_id
        existing_menu.query = {"agentCode": agent.code}
        logger.info(f"更新智能体菜单: {agent.code}")
    else:
        # 创建新菜单
        new_menu = Menu(
            name=data.menu_name,
            title=data.menu_name,
            path=menu_path,
            component="_core/agent-chat/index",
            type="agent",
            parent_id=data.menu_parent_id,
            icon=data.menu_icon,
            order=data.menu_order,
            application_id=agent.application_id,
            query={"agentCode": agent.code},
        )
        db.add(new_menu)
        logger.info(f"创建智能体菜单: {agent.code}")
    
    await db.commit()
    await db.refresh(agent)
    
    # 清理菜单缓存
    await MenuService.invalidate_cache()
    
    return await _build_agent_response(agent, db)


@router.post("/{agent_id}/unpublish-menu", response_model=ResponseModel, summary="取消发布智能体菜单")
async def unpublish_agent_menu(
    agent_id: str,
    db: AsyncSession = Depends(get_db),
):
    """取消发布智能体菜单（物理删除菜单）"""
    from core.menu.model import Menu
    from core.menu.service import MenuService
    
    # 获取智能体
    result = await db.execute(
        select(Agent).where(Agent.id == agent_id, Agent.is_deleted == False)
    )
    agent = result.scalar_one_or_none()
    if not agent:
        raise HTTPException(status_code=404, detail="智能体不存在")
    
    # 查找并删除菜单
    menu_path = f"/agent-chat/{agent.code}"
    menu_result = await db.execute(
        select(Menu).where(
            Menu.path == menu_path,
            Menu.is_deleted == False
        )
    )
    menu = menu_result.scalar_one_or_none()
    
    if menu:
        await db.delete(menu)
        await db.commit()
        await MenuService.invalidate_cache()
        logger.info(f"删除智能体菜单: {agent.code}")
    
    return ResponseModel(message="取消发布成功")


# ==================== Conversation API ====================

@router.get("/{agent_id}/conversations", response_model=PaginatedResponse[AgentConversationListResponse], summary="对话列表")
async def list_agent_conversations(
    agent_id: str,
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(20, ge=1, le=100, alias="pageSize", description="每页数量"),
    db: AsyncSession = Depends(get_db),
):
    """获取智能体的对话列表（仅返回当前用户的）"""
    current_user_id = get_current_user_id_from_context()
    query = select(AgentConversation).where(
        AgentConversation.agent_id == agent_id,
        AgentConversation.user_id == current_user_id,
        AgentConversation.is_deleted == False
    )
    
    # 获取总数
    count_result = await db.execute(select(func.count()).select_from(query.subquery()))
    total = count_result.scalar() or 0
    
    # 分页（按创建时间降序，最新的在前面）
    offset = (page - 1) * page_size
    query = query.order_by(AgentConversation.sys_create_datetime.desc())
    query = query.offset(offset).limit(page_size)
    
    result = await db.execute(query)
    conversations = result.scalars().all()
    
    # 获取智能体名称
    agent_result = await db.execute(
        select(Agent).where(Agent.id == agent_id)
    )
    agent = agent_result.scalar_one_or_none()
    agent_name = agent.name if agent else ""
    
    items = [
        {
            "id": c.id,
            "agent_id": c.agent_id,
            "agent_name": agent_name,
            "title": c.title or "",
            "message_count": c.message_count or 0,
            "sys_create_datetime": c.sys_create_datetime,
        }
        for c in conversations
    ]
    
    return PaginatedResponse(items=items, total=total)


@router.post("/{agent_id}/conversations", response_model=AgentConversationResponse, summary="创建对话")
async def create_agent_conversation(
    agent_id: str,
    data: AgentConversationCreate = None,
    db: AsyncSession = Depends(get_db),
):
    """创建新对话"""
    # 验证智能体
    agent_result = await db.execute(
        select(Agent).where(Agent.id == agent_id, Agent.is_deleted == False)
    )
    agent = agent_result.scalar_one_or_none()
    if not agent:
        raise HTTPException(status_code=404, detail="智能体不存在")
    
    title = data.title if data and data.title else "新建对话"
    
    current_user_id = get_current_user_id_from_context()
    conversation = AgentConversation(
        agent_id=agent_id,
        user_id=current_user_id,
        title=title,
    )
    db.add(conversation)
    await db.commit()
    await db.refresh(conversation)
    
    return {
        "id": conversation.id,
        "agent_id": conversation.agent_id,
        "agent_name": agent.name,
        "title": conversation.title or "",
        "summary": conversation.summary or "",
        "message_count": conversation.message_count or 0,
        "total_tokens": conversation.total_tokens or 0,
        "sys_create_datetime": conversation.sys_create_datetime,
        "sys_update_datetime": conversation.sys_update_datetime,
    }


@router.get("/conversations/{conversation_id}", response_model=AgentConversationResponse, summary="对话详情")
async def get_agent_conversation(conversation_id: str, db: AsyncSession = Depends(get_db)):
    """获取对话详情"""
    current_user_id = get_current_user_id_from_context()
    result = await db.execute(
        select(AgentConversation).where(
            AgentConversation.id == conversation_id,
            AgentConversation.user_id == current_user_id,
            AgentConversation.is_deleted == False
        )
    )
    conversation = result.scalar_one_or_none()
    if not conversation:
        raise HTTPException(status_code=404, detail="对话不存在")
    
    # 获取智能体名称
    agent_result = await db.execute(
        select(Agent).where(Agent.id == conversation.agent_id)
    )
    agent = agent_result.scalar_one_or_none()
    agent_name = agent.name if agent else ""
    
    return {
        "id": conversation.id,
        "agent_id": conversation.agent_id,
        "agent_name": agent_name,
        "title": conversation.title or "",
        "summary": conversation.summary or "",
        "message_count": conversation.message_count or 0,
        "total_tokens": conversation.total_tokens or 0,
        "sys_create_datetime": conversation.sys_create_datetime,
        "sys_update_datetime": conversation.sys_update_datetime,
    }


@router.delete("/conversations/{conversation_id}", response_model=ResponseModel, summary="删除对话")
async def delete_agent_conversation(conversation_id: str, db: AsyncSession = Depends(get_db)):
    """删除对话"""
    current_user_id = get_current_user_id_from_context()
    result = await db.execute(
        select(AgentConversation).where(
            AgentConversation.id == conversation_id,
            AgentConversation.user_id == current_user_id,
            AgentConversation.is_deleted == False
        )
    )
    conversation = result.scalar_one_or_none()
    if not conversation:
        raise HTTPException(status_code=404, detail="对话不存在")
    
    conversation.is_deleted = True
    await db.commit()
    
    return ResponseModel(message="删除成功")


@router.get("/conversations/{conversation_id}/messages", response_model=List[AgentMessageResponse], summary="消息列表")
async def list_agent_messages(
    conversation_id: str,
    limit: int = Query(50, ge=1, le=200, description="限制数量"),
    db: AsyncSession = Depends(get_db),
):
    """获取对话的消息列表"""
    current_user_id = get_current_user_id_from_context()
    # 验证对话存在且属于当前用户
    conv_result = await db.execute(
        select(AgentConversation).where(
            AgentConversation.id == conversation_id,
            AgentConversation.user_id == current_user_id,
            AgentConversation.is_deleted == False
        )
    )
    if not conv_result.scalar_one_or_none():
        raise HTTPException(status_code=404, detail="对话不存在")
    
    query = select(AgentMessage).where(
        AgentMessage.conversation_id == conversation_id,
        AgentMessage.is_deleted == False
    ).order_by(AgentMessage.sys_create_datetime).limit(limit)
    
    result = await db.execute(query)
    messages = result.scalars().all()
    
    return [
        {
            "id": m.id,
            "role": m.role,
            "content": m.content or "",
            "attachments": m.attachments or [],
            "status": m.status or "completed",
            "reasoning_steps": m.reasoning_steps or [],
            "tool_calls": m.tool_calls or [],
            "prompt_tokens": m.prompt_tokens or 0,
            "completion_tokens": m.completion_tokens or 0,
            "total_tokens": m.total_tokens or 0,
            "elapsed_time": m.elapsed_time or 0,
            "error_message": m.error_message or "",
            "feedback": m.feedback or "",
            "sys_create_datetime": m.sys_create_datetime,
        }
        for m in messages
    ]


@router.post("/messages/{message_id}/feedback", response_model=ResponseModel, summary="消息反馈")
async def feedback_agent_message(
    message_id: str,
    data: MessageFeedback,
    db: AsyncSession = Depends(get_db),
):
    """提交消息反馈"""
    result = await db.execute(
        select(AgentMessage).where(
            AgentMessage.id == message_id,
            AgentMessage.is_deleted == False
        )
    )
    message = result.scalar_one_or_none()
    if not message:
        raise HTTPException(status_code=404, detail="消息不存在")
    
    message.feedback = data.feedback
    await db.commit()
    
    return ResponseModel(message="反馈成功")


@router.post("/{agent_id}/chat", summary="智能体对话（流式，通过agent_id）")
async def chat_with_agent_by_id(
    agent_id: str,
    data: ChatInput,
    db: AsyncSession = Depends(get_db),
):
    """通过agent_id与智能体对话，自动创建或使用现有对话"""
    from ai_platform.services.agent_service import AgentService
    
    current_user_id = get_current_user_id_from_context()
    
    # 获取智能体
    agent_result = await db.execute(
        select(Agent).where(
            Agent.id == agent_id,
            Agent.is_deleted == False
        )
    )
    agent = agent_result.scalar_one_or_none()
    if not agent:
        raise HTTPException(status_code=404, detail="智能体不存在")
    
    # 如果提供了conversation_id，使用现有对话；否则创建新对话
    conversation_id = data.conversation_id if data.conversation_id else None
    
    if conversation_id:
        # 验证对话存在且属于当前用户
        conv_result = await db.execute(
            select(AgentConversation).where(
                AgentConversation.id == conversation_id,
                AgentConversation.agent_id == agent_id,
                AgentConversation.user_id == current_user_id,
                AgentConversation.is_deleted == False
            )
        )
        conversation = conv_result.scalar_one_or_none()
        if not conversation:
            raise HTTPException(status_code=404, detail="对话不存在")
    else:
        # 创建新对话
        conversation = AgentConversation(
            agent_id=agent_id,
            user_id=current_user_id,
            title="",
        )
        db.add(conversation)
        await db.flush()
    
    # 检查模型是否支持多模态（vision）
    supports_vision = getattr(agent, 'supports_vision', False)
    if agent.model_id:
        from ai_platform.models.model import LLMModel
        model_result = await db.execute(
            select(LLMModel).where(LLMModel.id == agent.model_id)
        )
        model = model_result.scalar_one_or_none()
        if model:
            supports_vision = model.supports_vision or False
    
    # 转换附件格式 - 从文件管理系统获取完整信息
    # 对于图片类型：
    #   - 多模态模型：获取 base64 编码以便 LLM 能够处理（LLM 无法访问内部 URL）
    #   - 非多模态模型：转换为文本描述
    # 对于文件类型，提取文本内容以便 LLM 能够理解文件内容
    import logging
    logging.info(f"Model supports_vision: {supports_vision}")
    attachments = None
    if data.attachments:
        from core.file_manager.service import FileManagerService
        attachments = []
        for att in data.attachments:
            logging.info(f"Processing attachment: file_id={att.file_id}, type={att.type}")
            file_obj = await FileManagerService.get_by_id(db, att.file_id)
            if file_obj:
                logging.info(f"Found file: name={file_obj.name}, mime_type={file_obj.mime_type}, size={file_obj.size}")
                attachment_data = {
                    'file_id': att.file_id,
                    'type': att.type,
                    'name': file_obj.name,
                    'url': file_obj.url or '',
                    'mime_type': file_obj.mime_type or '',
                    'size': file_obj.size or 0,
                }
                # 对于图片类型
                if att.type == 'image' and file_obj.mime_type and file_obj.mime_type.startswith('image/'):
                    if supports_vision:
                        # 多模态模型：获取 base64 编码
                        base64_content = await FileManagerService.get_file_as_base64(db, att.file_id)
                        if base64_content:
                            attachment_data['base64'] = base64_content
                            logging.info(f"Got base64 for image (vision model), length={len(base64_content)}")
                    else:
                        # 非多模态模型：使用阿里云 qwen-vl-ocr 识别图片内容
                        logging.info(f"Using OCR to recognize image for non-vision model: {file_obj.name}")
                        ocr_text = await FileManagerService.recognize_image_with_ocr(db, att.file_id)
                        if ocr_text:
                            attachment_data['text_content'] = f"[图片 OCR 识别结果: {file_obj.name}]\n{ocr_text}"
                            logging.info(f"OCR recognized text, length={len(ocr_text)}")
                        else:
                            size_kb = file_obj.size / 1024 if file_obj.size else 0
                            attachment_data['text_content'] = f"[图片: {file_obj.name}, 类型: {file_obj.mime_type}, 大小: {size_kb:.1f}KB]\n注意：OCR 识别失败，无法提取图片中的文字内容。"
                            logging.warning(f"OCR failed for image: {file_obj.name}")
                # 对于文件类型，提取文本内容
                elif att.type == 'file':
                    logging.info(f"Extracting text content from file: {file_obj.name}")
                    text_content = await FileManagerService.get_file_text_content(db, att.file_id)
                    if text_content:
                        attachment_data['text_content'] = text_content
                        logging.info(f"Extracted text content, length={len(text_content)}")
                    else:
                        logging.warning(f"Failed to extract text content from file: {file_obj.name}")
                attachments.append(attachment_data)
            else:
                logging.warning(f"File not found: {att.file_id}")
    
    async def generate():
        agent_service = AgentService(db)
        async for event in agent_service.chat(
            agent=agent,
            conversation=conversation,
            user_message=data.message,
            application_id=data.application_id,
            form_code=data.form_code,
            attachments=attachments,
        ):
            yield f"data: {json.dumps(event, ensure_ascii=False)}\n\n"
        yield "data: [DONE]\n\n"
    
    return StreamingResponse(
        generate(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
        }
    )


@router.post("/conversations/{conversation_id}/chat", summary="智能体对话（流式）")
async def chat_with_agent(
    conversation_id: str,
    data: ChatInput,
    db: AsyncSession = Depends(get_db),
):
    """与智能体对话，返回流式响应（SSE）"""
    from ai_platform.services.agent_service import AgentService
    
    current_user_id = get_current_user_id_from_context()
    
    # 验证对话存在且属于当前用户
    conv_result = await db.execute(
        select(AgentConversation).where(
            AgentConversation.id == conversation_id,
            AgentConversation.user_id == current_user_id,
            AgentConversation.is_deleted == False
        )
    )
    conversation = conv_result.scalar_one_or_none()
    if not conversation:
        raise HTTPException(status_code=404, detail="对话不存在")
    
    # 获取智能体
    agent_result = await db.execute(
        select(Agent).where(
            Agent.id == conversation.agent_id,
            Agent.is_deleted == False
        )
    )
    agent = agent_result.scalar_one_or_none()
    if not agent:
        raise HTTPException(status_code=404, detail="智能体不存在")
    
    # 检查模型是否支持多模态（vision）
    supports_vision = getattr(agent, 'supports_vision', False)
    if agent.model_id:
        from ai_platform.models.model import LLMModel
        model_result = await db.execute(
            select(LLMModel).where(LLMModel.id == agent.model_id)
        )
        model = model_result.scalar_one_or_none()
        if model:
            supports_vision = model.supports_vision or False
    
    # 转换附件格式 - 从文件管理系统获取完整信息
    # 对于图片类型：
    #   - 多模态模型：获取 base64 编码以便 LLM 能够处理（LLM 无法访问内部 URL）
    #   - 非多模态模型：转换为文本描述
    # 对于文件类型，提取文本内容以便 LLM 能够理解文件内容
    import logging
    logging.info(f"Model supports_vision: {supports_vision}")
    attachments = None
    if data.attachments:
        from core.file_manager.service import FileManagerService
        attachments = []
        for att in data.attachments:
            logging.info(f"Processing attachment: file_id={att.file_id}, type={att.type}")
            file_obj = await FileManagerService.get_by_id(db, att.file_id)
            if file_obj:
                logging.info(f"Found file: name={file_obj.name}, mime_type={file_obj.mime_type}, size={file_obj.size}")
                attachment_data = {
                    'file_id': att.file_id,
                    'type': att.type,
                    'name': file_obj.name,
                    'url': file_obj.url or '',
                    'mime_type': file_obj.mime_type or '',
                    'size': file_obj.size or 0,
                }
                # 对于图片类型
                if att.type == 'image' and file_obj.mime_type and file_obj.mime_type.startswith('image/'):
                    if supports_vision:
                        # 多模态模型：获取 base64 编码
                        base64_content = await FileManagerService.get_file_as_base64(db, att.file_id)
                        if base64_content:
                            attachment_data['base64'] = base64_content
                            logging.info(f"Got base64 for image (vision model), length={len(base64_content)}")
                    else:
                        # 非多模态模型：使用阿里云 qwen-vl-ocr 识别图片内容
                        logging.info(f"Using OCR to recognize image for non-vision model: {file_obj.name}")
                        ocr_text = await FileManagerService.recognize_image_with_ocr(db, att.file_id)
                        if ocr_text:
                            attachment_data['text_content'] = f"[图片 OCR 识别结果: {file_obj.name}]\n{ocr_text}"
                            logging.info(f"OCR recognized text, length={len(ocr_text)}")
                        else:
                            size_kb = file_obj.size / 1024 if file_obj.size else 0
                            attachment_data['text_content'] = f"[图片: {file_obj.name}, 类型: {file_obj.mime_type}, 大小: {size_kb:.1f}KB]\n注意：OCR 识别失败，无法提取图片中的文字内容。"
                            logging.warning(f"OCR failed for image: {file_obj.name}")
                # 对于文件类型，提取文本内容
                elif att.type == 'file':
                    logging.info(f"Extracting text content from file: {file_obj.name}")
                    text_content = await FileManagerService.get_file_text_content(db, att.file_id)
                    if text_content:
                        attachment_data['text_content'] = text_content
                        logging.info(f"Extracted text content, length={len(text_content)}")
                    else:
                        logging.warning(f"Failed to extract text content from file: {file_obj.name}")
                attachments.append(attachment_data)
            else:
                logging.warning(f"File not found: {att.file_id}")
    
    async def generate():
        agent_service = AgentService(db)
        async for event in agent_service.chat(
            agent=agent,
            conversation=conversation,
            user_message=data.message,
            application_id=data.application_id,
            form_code=data.form_code,
            attachments=attachments,
        ):
            yield f"data: {json.dumps(event, ensure_ascii=False)}\n\n"
        yield "data: [DONE]\n\n"
    
    return StreamingResponse(
        generate(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
        }
    )


# ==================== Helper Functions ====================

async def _build_agent_response(agent: Agent, db: AsyncSession) -> dict:
    """构建智能体输出"""
    # 获取模型名称
    model_name = ""
    if agent.model_id:
        model_result = await db.execute(
            select(LLMModel).where(LLMModel.id == agent.model_id)
        )
        model = model_result.scalar_one_or_none()
        model_name = model.display_name if model else ""
    
    # 获取工作流名称和类型
    workflow_name = ""
    workflow_type = "general"
    if agent.workflow_id:
        workflow_result = await db.execute(
            select(AIWorkflow).where(AIWorkflow.id == agent.workflow_id)
        )
        workflow = workflow_result.scalar_one_or_none()
        if workflow:
            workflow_name = workflow.name
            workflow_type = workflow.workflow_type or "general"
    
    return {
        "id": agent.id,
        "name": agent.name,
        "code": agent.code,
        "description": agent.description or "",
        "avatar": agent.avatar or "",
        "mode": agent.mode or "autonomous",
        "status": agent.status or "draft",
        "persona": agent.persona or {},
        "system_prompt": agent.system_prompt or "",
        "model_id": agent.model_id,
        "model_name": model_name,
        "temperature": agent.temperature or 0.7,
        "top_p": agent.top_p or 1.0,
        "max_tokens": agent.max_tokens or 4096,
        "max_iterations": agent.max_iterations or 10,
        "welcome_message": agent.welcome_message or "",
        "suggested_questions": agent.suggested_questions or [],
        "workflow_id": agent.workflow_id,
        "workflow_name": workflow_name,
        "workflow_type": workflow_type,
        "is_public": agent.is_public or False,
        "enable_memory": agent.enable_memory or False,
        "memory_window": agent.memory_window or 10,
        "enable_streaming": agent.enable_streaming if agent.enable_streaming is not None else True,
        "knowledge_base_ids": agent.knowledge_base_ids or [],
        "knowledge_config": agent.knowledge_config or {},
        "conversation_count": agent.conversation_count or 0,
        "message_count": agent.message_count or 0,
        "total_tokens": agent.total_tokens or 0,
        "sort": agent.sort or 0,
        "sys_create_datetime": agent.sys_create_datetime,
        "sys_update_datetime": agent.sys_update_datetime,
    }


def _build_agent_list_response(agent: Agent, model_name: str = "", application_name: str = "", has_menu: bool = False) -> dict:
    """构建智能体列表输出"""
    return {
        "id": agent.id,
        "application_id": agent.application_id,
        "application_name": application_name,
        "is_global": agent.is_global or False,
        "name": agent.name,
        "code": agent.code,
        "description": agent.description or "",
        "avatar": agent.avatar or "",
        "mode": agent.mode or "autonomous",
        "status": agent.status or "draft",
        "model_name": model_name,
        "is_public": agent.is_public or False,
        "conversation_count": agent.conversation_count or 0,
        "message_count": agent.message_count or 0,
        "has_menu": has_menu,
        "sys_create_datetime": agent.sys_create_datetime,
    }
