import fs from "node:fs"; import path from "node:path"; import type { NextRequest } from "next/server"; import { getItemByIdUnified } from "@/lib/db/queries/items"; import { buildItemImagePath } from "@/lib/item-images"; import { getItemById } from "@/lib/items-db"; export async function GET(req: NextRequest) { const { searchParams } = new URL(req.url); const relPath = searchParams.get("path") || ""; const itemId = searchParams.get("item"); const itemName = searchParams.get("name"); // Nome do item para validação (opcional) let imagePath: string | null = null; // Se foi fornecido um item ID, buscar o item no banco if (itemId) { try { const itemIdNum = parseInt(itemId, 10); if (!Number.isNaN(itemIdNum)) { // Tentar primeiro buscar na tabela unificada PostgreSQL // Se a tabela não existir, retornará null silenciosamente let item: any = null; item = await getItemByIdUnified(itemIdNum); // Se encontrou na tabela unificada, validar o nome se fornecido if (item && itemName && item.item_name) { if (item.item_name.toLowerCase() !== itemName.toLowerCase()) { // Nome não bate, ignorar este resultado item = null; } } // Se não encontrou na tabela unificada, tentar SQLite legado // Passar itemName para buscar por ID E NOME (evita ambiguidade) if (!item) { item = getItemById(itemIdNum, itemName || undefined); } if (item) { // PRIORIDADE: 1. image_local_path (local), 2. image_url (externa), 3. image (fallback) const imageLocalPath = item.image_local_path || ""; const imageUrl = item.image_url || ""; const image = item.image || ""; // Tentar primeiro a imagem local if (imageLocalPath) { const normalizedPath = imageLocalPath.replace(/\\/g, "/"); const category = ( item.categoria || item.category || "other" ).toLowerCase(); // Se já for um caminho completo (começa com data/), usar diretamente if (normalizedPath.startsWith("data/")) { imagePath = normalizedPath; } else { // Construir o caminho usando a função helper imagePath = buildItemImagePath(category, normalizedPath); } // Verificar se o arquivo existe antes de usar if (imagePath) { const baseDir = path.join(process.cwd(), "data", "images"); const resolved = path.join(process.cwd(), imagePath); if (resolved.startsWith(baseDir)) { try { await fs.promises.access(resolved); // Arquivo existe, usar este caminho } catch { // Arquivo não existe, tentar fallback externo imagePath = null; } } } } // Se não encontrou imagem local ou não existe, usar URL externa como fallback if (!imagePath && (imageUrl || image)) { const externalUrl = imageUrl || image; if ( externalUrl.startsWith("http://") || externalUrl.startsWith("https://") ) { return Response.redirect(externalUrl, 302); } } } } } catch (error) { console.error("[api/images] Erro ao buscar item:", error); } } else if (relPath) { // Se foi fornecido um path, usar diretamente imagePath = relPath; } if (!imagePath) { // Se não foi possível construir o caminho, retornar 404 ao invés de 400 // para evitar erros visíveis no console do navegador return new Response("Not Found", { status: 404 }); } // Permitir apenas caminhos sob data/images para segurança const baseDir = path.join(process.cwd(), "data", "images"); const resolved = path.join(process.cwd(), imagePath); if (!resolved.startsWith(baseDir)) { return new Response("Forbidden", { status: 403 }); } try { const file = await fs.promises.readFile(resolved); const ext = path.extname(resolved).toLowerCase(); const contentType = ext === ".gif" ? "image/gif" : ext === ".png" ? "image/png" : ext === ".webp" ? "image/webp" : ext === ".jpg" || ext === ".jpeg" ? "image/jpeg" : "application/octet-stream"; return new Response(file, { status: 200, headers: { "Content-Type": contentType }, }); } catch (error) { console.error("[api/images] Erro ao ler arquivo:", error); // Retornar 404 silenciosamente para não gerar erros no console return new Response("Not Found", { status: 404 }); } }