from fastapi import APIRouter, Depends, Query from uuid import UUID from sqlalchemy.ext.asyncio import AsyncSession from database.postgres import get_pg_session from auth.dependencies import require_permission from auth.models import TokenPayload from tickets import service from tickets.models import TicketCreate, TicketUpdate, MessageCreate, EscalateIn, TicketOut, TicketListResponse from shared.audit import log_action router = APIRouter(prefix="/api/tickets", tags=["tickets"]) @router.get("", response_model=TicketListResponse) async def list_tickets( status: str | None = Query(None), priority: str | None = Query(None), customer_id: str | None = Query(None), page: int = Query(1, ge=1), limit: int = Query(25, ge=1, le=100), db: AsyncSession = Depends(get_pg_session), _user: TokenPayload = Depends(require_permission("crm", "view")), ): rows, total = await service.list_tickets(db, status, priority, customer_id, page, limit) return {"data": rows, "pagination": {"page": page, "limit": limit, "total": total}} @router.get("/by-customer/{customer_id}", response_model=list[TicketOut]) async def list_by_customer( customer_id: str, db: AsyncSession = Depends(get_pg_session), _user: TokenPayload = Depends(require_permission("crm", "view")), ): return await service.list_by_customer(db, customer_id) @router.get("/by-device/{device_id}", response_model=list[TicketOut]) async def list_by_device( device_id: str, db: AsyncSession = Depends(get_pg_session), _user: TokenPayload = Depends(require_permission("crm", "view")), ): return await service.list_by_device(db, device_id) @router.get("/{ticket_id}", response_model=TicketOut) async def get_ticket( ticket_id: UUID, db: AsyncSession = Depends(get_pg_session), _user: TokenPayload = Depends(require_permission("crm", "view")), ): return await service.get_ticket(db, ticket_id) @router.post("", response_model=TicketOut, status_code=201) async def create_ticket( body: TicketCreate, db: AsyncSession = Depends(get_pg_session), _user: TokenPayload = Depends(require_permission("crm", "add")), ): ticket = await service.create_ticket(db, body) await log_action(db, _user.sub, _user.name or _user.email, "CREATE", "ticket", str(ticket.id), ticket.subject) return ticket @router.patch("/{ticket_id}", response_model=TicketOut) async def update_ticket( ticket_id: UUID, body: TicketUpdate, db: AsyncSession = Depends(get_pg_session), _user: TokenPayload = Depends(require_permission("crm", "edit")), ): ticket = await service.update_ticket(db, ticket_id, body) action = "STATUS_CHANGE" if body.status is not None else "UPDATE" await log_action(db, _user.sub, _user.name or _user.email, action, "ticket", str(ticket_id), ticket.subject) return ticket @router.post("/{ticket_id}/messages", response_model=TicketOut) async def add_message( ticket_id: UUID, body: MessageCreate, db: AsyncSession = Depends(get_pg_session), _user: TokenPayload = Depends(require_permission("crm", "edit")), ): ticket = await service.add_message(db, ticket_id, body) await log_action(db, _user.sub, _user.name or _user.email, "UPDATE", "ticket", str(ticket_id), ticket.subject, meta={"action_detail": "message_added"}) return ticket @router.post("/{ticket_id}/escalate", response_model=TicketOut) async def escalate( ticket_id: UUID, body: EscalateIn, db: AsyncSession = Depends(get_pg_session), _user: TokenPayload = Depends(require_permission("crm", "edit")), ): ticket = await service.escalate_to_issue(db, ticket_id, body.entry_id) await log_action(db, _user.sub, _user.name or _user.email, "STATUS_CHANGE", "ticket", str(ticket_id), ticket.subject, meta={"action_detail": "escalated_to_issue"}) return ticket