from fastapi import APIRouter, HTTPException, Query, Depends from typing import Dict, List, Optional from pydantic import BaseModel from services.role_service import role_service from services.device_service import device_service from services.history_service import history_service from api.auth import api_auth router = APIRouter(prefix="/api/roles") class RoleResponse(BaseModel): role_key: str name: str description: Optional[str] = None languages: Optional[List[str]] = None class RoleSummaryResponse(BaseModel): role_key: str name: str class DeviceRoleUpdate(BaseModel): role_key: str language: Optional[str] = None class ConversationMessage(BaseModel): user: str assistant: str timestamp: Optional[float] = None class PaginatedRoleResponse(BaseModel): total: int page: int page_size: int data: List[RoleResponse] class PaginatedHistoryResponse(BaseModel): total: int page: int page_size: int data: List[ConversationMessage] role_key: str role_name: str @router.get("/list", response_model=PaginatedRoleResponse) async def list_roles( authenticated_device_id: str = Depends(api_auth), page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=100), search: Optional[str] = None ): """获取角色分页列表,支持搜索""" return await role_service.get_roles_paginated(page, page_size, search) @router.get("/summaries", response_model=List[RoleSummaryResponse]) async def get_role_summaries( authenticated_device_id: str = Depends(api_auth) ): """获取角色简要信息列表(仅包含key和name)""" return await role_service.get_role_summaries() @router.get("/device/{device_id}") async def get_device_role( device_id: str, authenticated_device_id: str = Depends(api_auth) ): """获取设备当前使用的角色""" if device_id != authenticated_device_id: raise HTTPException(status_code=403, detail="无权访问其他设备的配置") return await device_service.get_device_role(device_id) @router.put("/device/{device_id}") async def update_device_role( device_id: str, role_update: DeviceRoleUpdate, authenticated_device_id: str = Depends(api_auth) ): """更新设备的角色配置""" if device_id != authenticated_device_id: raise HTTPException(status_code=403, detail="无权修改其他设备的配置") try: return await device_service.update_device_role( device_id, role_update.role_key, role_update.language ) except ValueError as e: raise HTTPException(status_code=404, detail=str(e)) except Exception as e: raise HTTPException(status_code=500, detail=f"更新角色时出错: {str(e)}") @router.get("/history/{device_id}", response_model=PaginatedHistoryResponse) async def get_conversation_history( device_id: str, authenticated_device_id: str = Depends(api_auth), role_key: Optional[str] = None, page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=100), since: Optional[float] = None, until: Optional[float] = None ): """获取设备的对话历史记录,支持分页和时间范围筛选""" if device_id != authenticated_device_id: raise HTTPException(status_code=403, detail="无权访问其他设备的对话历史") try: return await history_service.get_history_paginated( device_id, role_key, page, page_size, since, until ) except Exception as e: raise HTTPException(status_code=500, detail=f"获取对话历史失败: {str(e)}") @router.get("/history-summary/{device_id}") async def get_conversation_history_summary( device_id: str, authenticated_device_id: str = Depends(api_auth), days: int = Query(7, ge=1, le=30) ): """获取设备的对话历史摘要信息,包括每个角色的最后交互时间和消息数量""" if device_id != authenticated_device_id: raise HTTPException(status_code=403, detail="无权访问其他设备的对话历史摘要") try: return await history_service.get_history_summary(device_id, days) except Exception as e: raise HTTPException(status_code=500, detail=f"获取对话历史摘要失败: {str(e)}")