from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.exc import SQLAlchemyError from app.services.db_manager import DatabaseManager from instance.configdb import get_database_manager from uuid import UUID from pydantic import BaseModel from enum import Enum from typing import List, Literal, Optional from datetime import datetime import logging logger = logging.getLogger(__name__) class TicketStatus(str, Enum): OPEN = "open" PENDING = "pending" CLOSED = "closed" class CreateTicketRequest(BaseModel): subject: str message: str class TicketResponse(BaseModel): id: int user_id: UUID subject: str message: str status: TicketStatus created_at: datetime updated_at: datetime class TicketMessageRequest(BaseModel): message: str class TicketMessageResponse(BaseModel): id: int ticket_id: int sender: str message: str created_at: datetime router = APIRouter() def handle_exception(e: Exception, message: str): logger.error(f"{message}: {e}") raise HTTPException(status_code=500, detail=f"{message}: {str(e)}") @router.post("/support/tickets/{ticket_id}/messages", response_model=TicketMessageResponse, summary="Добавить сообщение") async def add_message( ticket_id: int, request: TicketMessageRequest, sender: Literal["user", "support"], # "user" или "support" database_manager: DatabaseManager = Depends(get_database_manager) ): """ Добавляет сообщение в тикет. Args: ticket_id (int): ID тикета. request (TicketMessageRequest): Данные сообщения. sender (str): Отправитель ("user" или "support"). database_manager (DatabaseManager): Управление базой данных. Returns: TicketMessageResponse: Данные созданного сообщения. """ try: message = await database_manager.add_ticket_message(ticket_id=ticket_id, sender=sender, message=request.message) if not message: raise HTTPException(status_code=404, detail="Тикет не найден или ошибка добавления сообщения") return message except Exception as e: handle_exception(e,"Ошибка добавления сообщения") @router.get("/support/tickets/{ticket_id}/messages", response_model=List[TicketMessageResponse], summary="Получить сообщения") async def get_messages( ticket_id: int, database_manager: DatabaseManager = Depends(get_database_manager) ): """ Возвращает список сообщений в тикете. Args: ticket_id (int): ID тикета, для которого нужно получить сообщения. database_manager (DatabaseManager): Менеджер базы данных. Returns: List[TicketMessageResponse]: Список сообщений, связанных с тикетом. Raises: HTTPException: 404, если сообщения для тикета не найдены. HTTPException: 500, если произошла ошибка на сервере. """ try: messages = await database_manager.get_ticket_messages(ticket_id=ticket_id) if not messages: raise HTTPException(status_code=404, detail="Сообщения для тикета не найдены") return messages except Exception as e: handle_exception(e,"Ошибка получения сообщения") @router.post("/support/tickets", response_model=TicketResponse, summary="Создать тикет") async def create_ticket( request: CreateTicketRequest, user_id: UUID, database_manager: DatabaseManager = Depends(get_database_manager) ): """ Создаёт новый тикет для пользователя. Args: request (CreateTicketRequest): Данные для создания тикета (тема и сообщение). user_id (UUID): Идентификатор пользователя, создающего тикет. database_manager (DatabaseManager): Менеджер базы данных. Returns: TicketResponse: Данные созданного тикета. Raises: HTTPException: 500, если произошла ошибка при создании тикета. """ try: ticket = await database_manager.create_ticket( user_id=user_id, subject=request.subject, message=request.message ) return ticket except Exception as e: handle_exception(e,"Ошибка содания тикета") @router.get("/support/tickets", response_model=List[TicketResponse], summary="Получить список тикетов") async def list_tickets( user_id: UUID, database_manager: DatabaseManager = Depends(get_database_manager) ): """ Возвращает список тикетов пользователя. Args: user_id (UUID): Идентификатор пользователя, чьи тикеты нужно получить. database_manager (DatabaseManager): Менеджер базы данных. Returns: List[TicketResponse]: Список тикетов пользователя. Raises: HTTPException: 404, если тикеты не найдены. HTTPException: 500, если произошла ошибка на сервере. """ try: tickets = await database_manager.list_tickets(user_id=user_id) if not tickets: raise HTTPException(status_code=404, detail="Тикеты не найдены") return tickets except Exception as e: handle_exception(e,"Ошибка получения тикетов") @router.patch("/support/tickets/{ticket_id}", response_model=TicketResponse, summary="Обновить статус тикета") async def update_ticket_status( ticket_id: int, status: TicketStatus, database_manager: DatabaseManager = Depends(get_database_manager) ): """ Обновляет статус тикета. Args: ticket_id (int): ID тикета, статус которого нужно обновить. status (TicketStatus): Новый статус тикета (open, pending, closed). database_manager (DatabaseManager): Менеджер базы данных. Returns: TicketResponse: Обновлённые данные тикета. Raises: HTTPException: 404, если тикет не найден. HTTPException: 500, если произошла ошибка при обновлении тикета. """ try: ticket = await database_manager.update_ticket_status(ticket_id=ticket_id, status=status) if not ticket: raise HTTPException(status_code=404, detail="Тикет не найден") return ticket except Exception as e: handle_exception(e,"Ошибка обновления тикета")