import { secureLogger } from "@/lib/secure-logger"; interface GenerateItemStructureInput { name: string; description: string; scope: "global" | "server"; server?: string | null; } interface GeminiResponse { structure: { table: string; columns: Record; }; raw: unknown; } const FALLBACK_STRUCTURE = { table: "items_all", columns: { name: "Final Fate", description: "Item lendário utilizado no slot de tocha. Oferece bônus massivos em skills mágicas, velocidade e efeitos de leech.", attributes: { shielding: 20, death_magic: 120, mana_leech: { value: 30, chance: 100 }, life_leech: { value: 25, chance: 100 }, critical_hit: { damage: 25, chance: 75 }, speed: 1000, protection_physical: 40, damage_reflection: 80, }, }, }; export async function generateItemStructure( input: GenerateItemStructureInput ): Promise { const apiKey = process.env.GEMINI_API_KEY; if (!apiKey) { secureLogger.warn("⚠️ GEMINI_API_KEY ausente – utilizando fallback estático."); return { structure: FALLBACK_STRUCTURE, raw: FALLBACK_STRUCTURE, }; } const url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=" + apiKey; const prompt = buildPrompt(input); try { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ contents: [ { role: "user", parts: [{ text: prompt }], }, ], generationConfig: { temperature: 0, topP: 0.1, }, }), }); if (!response.ok) { throw new Error(`Gemini retornou status ${response.status}`); } const data = await response.json(); const text = data?.candidates?.[0]?.content?.parts?.[0]?.text ?? data?.candidates?.[0]?.output_text; if (!text) { throw new Error("Resposta do Gemini vazia ou inválida."); } const cleaned = text .replace(/```json/gi, "") .replace(/```/g, "") .trim(); const parsed = JSON.parse(cleaned); return { structure: parsed, raw: data, }; } catch (error) { secureLogger.error("❌ Falha ao gerar estrutura via Gemini", { error: error instanceof Error ? error.message : "Erro desconhecido", }); return { structure: FALLBACK_STRUCTURE, raw: FALLBACK_STRUCTURE, }; } } function buildPrompt({ name, description, scope, server }: GenerateItemStructureInput) { return ` Você é um assistente que prepara carga útil em JSON para inserção de itens em banco de dados. Requisitos obrigatórios: - Responda SOMENTE com JSON válido, sem comentários, sem markdown, sem texto adicional. - Formato esperado: { "table": "nome_da_tabela", "columns": { "...": "..." } } - Nunca inclua explicações fora do JSON. Contexto do item: - Nome: ${name} - Escopo: ${scope === "server" ? `específico do servidor ${server ?? "não informado"}` : "global"} - Descrição original (mantenha estrutura e extrair atributos quando possível): """ ${description} """ Instruções: - Escolha uma tabela coerente com o escopo (ex.: "items_all" para global ou "items_${(server ?? "custom") .toLowerCase() .replace(/[^a-z0-9]+/g, "_")}" para servidor). - Dentro de "columns", inicie com "name" e "description". - Modele atributos numéricos em objetos ou subtabelas conforme necessário (ex.: {"attributes": {...}}). - Quando não tiver certeza de um campo, deixe nulo. - Nunca invente dados além do que estiver na descrição. - Garante que o JSON seja minuciosamente válido. `; }