import { NextResponse } from "next/server" import { ConvexHttpClient } from "convex/browser" import { api } from "@/convex/_generated/api" import type { Id } from "@/convex/_generated/dataModel" import { assertAuthenticatedSession } from "@/lib/auth-server" import { DEFAULT_TENANT_ID } from "@/lib/constants" import { requireConvexUrl } from "@/server/convex-client" export const runtime = "nodejs" const MAX_RESULTS = 10 type TicketRecord = { id: string | number reference: string | number subject?: string | null status?: string | null priority?: string | null requester?: { name?: string | null } | null assignee?: { name?: string | null } | null company?: { name?: string | null } | null updatedAt?: number | null } function isTicketRecord(value: unknown): value is TicketRecord { if (!value || typeof value !== "object") { return false } const record = value as Record const hasValidId = typeof record.id === "string" || typeof record.id === "number" const hasValidReference = typeof record.reference === "string" || typeof record.reference === "number" return hasValidId && hasValidReference } function normalizeRole(role?: string | null) { return (role ?? "").toLowerCase() } export async function GET(request: Request) { const session = await assertAuthenticatedSession() if (!session) { return NextResponse.json({ items: [] }, { status: 401 }) } const normalizedRole = normalizeRole(session.user.role) const isAgentOrAdmin = normalizedRole === "admin" || normalizedRole === "agent" const canLinkOwnTickets = normalizedRole === "collaborator" if (!isAgentOrAdmin && !canLinkOwnTickets) { return NextResponse.json({ items: [] }, { status: 403 }) } const tenantId = session.user.tenantId ?? DEFAULT_TENANT_ID const url = new URL(request.url) const rawQuery = url.searchParams.get("q") ?? "" const query = rawQuery.trim() const client = new ConvexHttpClient(requireConvexUrl()) // Garantir que o usuário exista no Convex para obter viewerId let viewerId: string | null = null try { const ensured = await client.mutation(api.users.ensureUser, { tenantId, name: session.user.name ?? session.user.email, email: session.user.email, avatarUrl: session.user.avatarUrl ?? undefined, role: session.user.role.toUpperCase(), }) viewerId = ensured?._id ?? null } catch (error) { console.error("[mentions] ensureUser failed", error) return NextResponse.json({ items: [] }, { status: 500 }) } if (!viewerId) { return NextResponse.json({ items: [] }, { status: 403 }) } // Pesquisar pelos tickets visíveis ao viewer (assunto, resumo ou #referência) let tickets: TicketRecord[] = [] try { const res = await client.query(api.tickets.list, { tenantId, viewerId: viewerId as unknown as Id<"users">, search: query, limit: 40, }) tickets = Array.isArray(res) ? res.filter(isTicketRecord) : [] } catch (error) { console.error("[mentions] tickets.list failed", error) return NextResponse.json({ items: [] }, { status: 500 }) } const basePath = isAgentOrAdmin ? "/tickets" : "/portal/tickets" const items = tickets.slice(0, MAX_RESULTS).map((t) => ({ id: String(t.id), reference: Number(t.reference), subject: String(t.subject ?? ""), status: String(t.status ?? "PENDING"), priority: String(t.priority ?? "MEDIUM"), requesterName: t.requester?.name ?? null, assigneeName: t.assignee?.name ?? null, companyName: t.company?.name ?? null, url: `${basePath}/${String(t.id)}`, updatedAt: t.updatedAt ? new Date(t.updatedAt).toISOString() : new Date().toISOString(), })) return NextResponse.json({ items }) }