Files
2025-11-11 03:08:36 -03:00

267 lines
8.1 KiB
TypeScript

/**
* GET /api/chats - Lista chats do usuário
* POST /api/chats - Cria novo chat
*/
import { type NextRequest, NextResponse } from "next/server";
import { requireAuth } from "@/lib/auth/middleware";
import { connectMongoDB } from "@/lib/mongodb/connection";
import { Chat } from "@/lib/mongodb/models/Chat";
import { getMainCharacter } from "@/lib/prisma/queries/characters";
import { getListingById } from "@/lib/prisma/queries/listings";
import { getUserById } from "@/lib/prisma/queries/users";
import { secureLogger } from "@/lib/secure-logger";
import { createChatSchema } from "@/lib/validation/chat-schemas";
/**
* GET /api/chats
* Lista todos os chats do usuário autenticado
*/
export async function GET(request: NextRequest) {
try {
const authResult = await requireAuth(request);
if (authResult instanceof NextResponse) return authResult;
const auth = authResult;
await connectMongoDB();
// Buscar todos os chats do usuário (como comprador ou vendedor)
const chats = await Chat.find({
$or: [{ buyer_id: auth.userId }, { seller_id: auth.userId }],
is_active: true,
})
.sort({ updated_at: -1 })
.limit(100);
// Serializar datas
const serializedChats = chats.map((chat) => ({
chat_id: chat.chat_id,
listing_id: chat.listing_id,
buyer_id: chat.buyer_id,
seller_id: chat.seller_id,
created_at: chat.created_at.toISOString(),
updated_at: chat.updated_at.toISOString(),
last_message_at: chat.last_message_at?.toISOString() || null,
last_message_preview: chat.last_message_preview,
buyer_unread_count: chat.buyer_unread_count,
seller_unread_count: chat.seller_unread_count,
is_active: chat.is_active,
listing_cache: chat.listing_cache,
buyer_cache: chat.buyer_cache,
seller_cache: chat.seller_cache,
}));
return NextResponse.json(
{
success: true,
chats: serializedChats,
count: serializedChats.length,
},
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao buscar chats", {
error: error instanceof Error ? error.message : "Erro desconhecido",
stack: error instanceof Error ? error.stack : undefined,
});
return NextResponse.json(
{ success: false, error: "Erro ao buscar chats" },
{ status: 500 },
);
}
}
/**
* POST /api/chats
* Cria um novo chat entre comprador e vendedor
*/
export async function POST(request: NextRequest) {
try {
const authResult = await requireAuth(request);
if (authResult instanceof NextResponse) return authResult;
const auth = authResult;
const body = await request.json();
const validationResult = createChatSchema.safeParse(body);
if (!validationResult.success) {
return NextResponse.json(
{
success: false,
error: "Dados inválidos",
details: validationResult.error.issues,
},
{ status: 400 },
);
}
const { listing_id, buyer_message } = validationResult.data;
await connectMongoDB();
// Buscar anúncio
const listing = await getListingById(listing_id);
if (!listing) {
return NextResponse.json(
{ success: false, error: "Anúncio não encontrado" },
{ status: 404 },
);
}
// Verificar se não é o próprio vendedor
if (listing.seller_id === auth.userId) {
return NextResponse.json(
{ success: false, error: "Você não pode criar um chat com você mesmo" },
{ status: 400 },
);
}
// Verificar se anúncio está ativo
if (listing.listing_status !== "active") {
return NextResponse.json(
{ success: false, error: "Anúncio não está disponível para chat" },
{ status: 400 },
);
}
// Gerar chat_id único
const chat_id = `${listing_id}_${auth.userId}_${listing.seller_id}`;
// Verificar se chat já existe
let chat = await Chat.findOne({ chat_id });
if (chat) {
// Chat já existe, retornar
return NextResponse.json(
{
success: true,
chat: {
chat_id: chat.chat_id,
listing_id: chat.listing_id,
buyer_id: chat.buyer_id,
seller_id: chat.seller_id,
created_at: chat.created_at.toISOString(),
updated_at: chat.updated_at.toISOString(),
last_message_at: chat.last_message_at?.toISOString() || null,
last_message_preview: chat.last_message_preview,
buyer_unread_count: chat.buyer_unread_count,
seller_unread_count: chat.seller_unread_count,
is_active: chat.is_active,
listing_cache: chat.listing_cache,
buyer_cache: chat.buyer_cache,
seller_cache: chat.seller_cache,
},
already_exists: true,
},
{ status: 200 },
);
}
// Buscar dados do comprador
const buyer = await getUserById(auth.userId);
if (!buyer) {
return NextResponse.json(
{ success: false, error: "Usuário não encontrado" },
{ status: 404 },
);
}
const buyerCharacter = await getMainCharacter(auth.userId);
// Buscar dados do vendedor
const seller = await getUserById(listing.seller_id);
if (!seller) {
return NextResponse.json(
{ success: false, error: "Vendedor não encontrado" },
{ status: 404 },
);
}
const sellerCharacter = await getMainCharacter(listing.seller_id);
// Criar chat
chat = new Chat({
chat_id,
listing_id,
buyer_id: auth.userId,
seller_id: listing.seller_id,
listing_cache: {
item_name: listing.item_name,
item_image_url: null, // Imagem será obtida via item_id se necessário
price_pix: listing.price_pix ? Number(listing.price_pix) : null,
price_tibia_coins: listing.price_tibia_coins || null,
price_gold_coins: listing.price_gold_coins
? Number(listing.price_gold_coins)
: null,
server_name: listing.server_name,
listing_status: listing.listing_status,
},
buyer_cache: {
user_id: buyer.user_id,
username: buyer.username,
character_name: buyerCharacter?.character_name || null,
},
seller_cache: {
user_id: seller.user_id,
username: seller.username,
character_name: sellerCharacter?.character_name || null,
},
});
await chat.save();
// Se houver mensagem inicial, criar
if (buyer_message && buyer_message.trim().length > 0) {
const { Message } = await import("@/lib/mongodb/models/Message");
const message = new Message({
chat_id,
sender_id: auth.userId,
content: buyer_message.trim(),
message_type: "text",
});
await message.save();
// Atualizar chat
chat.last_message_at = new Date();
chat.last_message_preview = buyer_message.substring(0, 100);
chat.seller_unread_count = 1;
await chat.save();
}
return NextResponse.json(
{
success: true,
chat: {
chat_id: chat.chat_id,
listing_id: chat.listing_id,
buyer_id: chat.buyer_id,
seller_id: chat.seller_id,
created_at: chat.created_at.toISOString(),
updated_at: chat.updated_at.toISOString(),
last_message_at: chat.last_message_at?.toISOString() || null,
last_message_preview: chat.last_message_preview,
buyer_unread_count: chat.buyer_unread_count,
seller_unread_count: chat.seller_unread_count,
is_active: chat.is_active,
listing_cache: chat.listing_cache,
buyer_cache: chat.buyer_cache,
seller_cache: chat.seller_cache,
},
already_exists: false,
},
{ status: 201 },
);
} catch (error) {
secureLogger.error("❌ Erro ao criar chat", {
error: error instanceof Error ? error.message : "Erro desconhecido",
stack: error instanceof Error ? error.stack : undefined,
});
return NextResponse.json(
{ success: false, error: "Erro ao criar chat" },
{ status: 500 },
);
}
}