from typing import Any, Dict, List, Optional from fastapi import APIRouter, Depends, HTTPException from models.document import DocumentNode from models.user import User from pydantic import BaseModel from services.document_service import document_service from routers.auth import get_current_user router = APIRouter() class CreateDocumentRequest(BaseModel): title: str type: str # "book", "chapter", "scene" parent_id: Optional[str] = None content: str = "" class UpdateDocumentRequest(BaseModel): title: Optional[str] = None content: Optional[str] = None parent_id: Optional[str] = None # Для переноса order: Optional[int] = None def _get_user_project(project_id: str, current_user: User) -> None: """Проверить что проект принадлежит пользователю""" from services.project_service import project_service project = project_service.get_project(project_id) if not project: raise HTTPException(status_code=404, detail="Project not found") if project.user_id != current_user.id: raise HTTPException(status_code=403, detail="Access denied") @router.get( "/projects/{project_id}/documents/tree", response_model=List[Dict[str, Any]] ) async def get_documents_tree( project_id: str, current_user: User = Depends(get_current_user) ): """Получить документы в виде дерева""" _get_user_project(project_id, current_user) return document_service.get_documents_tree(project_id, current_user.id) @router.get("/projects/{project_id}/documents", response_model=List[DocumentNode]) async def get_all_documents( project_id: str, current_user: User = Depends(get_current_user) ): """Получить все документы (плоский список)""" _get_user_project(project_id, current_user) return document_service.get_all_documents(project_id, current_user.id) @router.get( "/projects/{project_id}/documents/{document_id}", response_model=DocumentNode ) async def get_document( project_id: str, document_id: str, current_user: User = Depends(get_current_user), ): """Получить документ по ID""" _get_user_project(project_id, current_user) document = document_service.get_document(project_id, document_id, current_user.id) if not document: raise HTTPException(status_code=404, detail="Document not found") return document @router.post( "/projects/{project_id}/documents", response_model=DocumentNode, status_code=201 ) async def create_document( project_id: str, request: CreateDocumentRequest, current_user: User = Depends(get_current_user), ): """Создать новый документ""" _get_user_project(project_id, current_user) try: return document_service.create_document( project_id=project_id, title=request.title, doc_type=request.type, user_id=current_user.id, parent_id=request.parent_id, content=request.content, ) except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) @router.put( "/projects/{project_id}/documents/{document_id}", response_model=DocumentNode ) async def update_document( project_id: str, document_id: str, request: UpdateDocumentRequest, current_user: User = Depends(get_current_user), ): """Обновить документ (включая перенос)""" _get_user_project(project_id, current_user) try: document = document_service.update_document( project_id=project_id, document_id=document_id, user_id=current_user.id, title=request.title, content=request.content, parent_id=request.parent_id, order=request.order, ) if not document: raise HTTPException(status_code=404, detail="Document not found") return document except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) @router.delete("/projects/{project_id}/documents/{document_id}") async def delete_document( project_id: str, document_id: str, current_user: User = Depends(get_current_user), ): """Удалить документ с каскадом""" _get_user_project(project_id, current_user) success = document_service.delete_document(project_id, document_id, current_user.id) if not success: raise HTTPException(status_code=404, detail="Document not found") return {"status": "deleted", "document_id": document_id} @router.get( "/projects/{project_id}/documents/{parent_id}/children", response_model=List[DocumentNode], ) async def get_children( project_id: str, parent_id: str, current_user: User = Depends(get_current_user), ): """Получить прямых детей узла""" _get_user_project(project_id, current_user) return document_service.get_children(project_id, parent_id, current_user.id)