import { GoogleGenAI } from "@google/genai"; import { AggregatedData } from "./types"; // Declare process to avoid TypeScript errors without causing aggressive bundler shims declare const process: any; const SYSTEM_INSTRUCTION = ` You are an expert Key Account Manager (KAM) and Senior Sales Strategist for "Craze Analytix". Your specialty is analyzing retail data, advertising performance, and market trends to provide high-level strategic recommendations. You have access to a detailed report of the currently filtered sales and advertising data. The data includes Sell Out (€), Units Sold, Product Lines, Customer Markets, Seasonality (Monthly Trends), and Growth/Decline metrics. Your objective: 1. **Analyze**: Deeply study the provided data according to the user's specific query. 2. **Opinion**: Provide expert opinions on the health of the business, product performance, or market position. 3. **Recommendations**: Give actionable, professional advice to improve sales, ROAS, stock health, or market share. Guidelines: - Maintain a professional, consultative, and business-driven tone (KAM style). - Always justify your recommendations with specific numbers from the data. - If asked about "Trends" or "Seasonality", look at the Monthly Seasonality section. - If asked about "Growth" or "Decline", look at the Top/Bottom Movers sections. - When comparing metrics, calculate variances or ratios if relevant (e.g. Sales vs Ads growth). - Format your response with clear headers and bullet points for readability. - Respond in the same language as the user's question (e.g., if they ask in Spanish, answer in Spanish). `; // Helper to get API key safely const getApiKey = (): string | undefined => { try { return process.env.API_KEY; } catch (e) { return undefined; } }; const formatCurrency = (val: number) => `€${val.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 })}`; const formatUnits = (val: number) => `${val.toLocaleString('de-DE')} units`; export const queryGemini = async ( question: string, context: AggregatedData, filteredRecordCount: number ): Promise => { const apiKey = getApiKey(); if (!apiKey) { return "API Key is missing. Please configure your environment variables (API_KEY) or check your .env file."; } try { const ai = new GoogleGenAI({ apiKey }); // --- CONTEXT GENERATION --- // We construct a structured report mirroring the dashboard charts // 1. Totals by Year (KPI Cards) const yearlySummary = Object.entries(context.totalsByYear) .sort((a, b) => parseInt(b[0]) - parseInt(a[0])) // Descending years .map(([year, data]) => ` - ${year}: ${formatCurrency(data.sellOut)} | ${formatUnits(data.units)}`) .join('\n'); // 2. Seasonality (Line Chart Data) // We simplify this to a CSV-like list for the AI to parse trends const seasonalitySummary = context.seasonality.map(p => { // Extract values for each year in the point const yearValues = context.availableYears.map(y => `${y}: ${formatCurrency(p[y] as number || 0)}`).join(', '); return ` - ${p.name}: [${yearValues}]`; }).join('\n'); // 3. Top Movers (Growth Table) - Limit to Top 10 const growthSummary = context.topMovers.slice(0, 10).map(m => ` - ${m.line}: +€${m.sellOutGrowthValue.toLocaleString('de-DE')} (${m.sellOutGrowthPercentage.toFixed(1)}%)` ).join('\n'); // 4. Declining Movers (Decline Table) - Limit to Top 10 const declineSummary = context.bottomMovers.slice(0, 10).map(m => ` - ${m.line}: -€${Math.abs(m.sellOutGrowthValue).toLocaleString('de-DE')} (${m.sellOutGrowthPercentage.toFixed(1)}%)` ).join('\n'); // 5. Product Lines Overview (Bar Charts) - Limit to Top 50 to save tokens but give depth const topLinesSummary = context.byLine.slice(0, 50).map((l, i) => ` ${i + 1}. ${l.name}: ${formatCurrency(l.value)} | ${formatUnits(l.units)}` ).join('\n'); // 6. Customer Distribution (Customer Chart) const customerSummary = context.byCustomer.map(c => ` - ${c.name}: ${formatCurrency(c.value)}` ).join('\n'); const fullReport = ` REPORT CONTEXT: ---------------- GLOBAL TOTALS: Total Sell Out: ${formatCurrency(context.totalSellOut)} Total Units: ${formatUnits(context.totalUnits)} Records Analyzed: ${filteredRecordCount} Years Available: ${context.availableYears.join(', ')} YEARLY BREAKDOWN: ${yearlySummary} MONTHLY SEASONALITY (Revenue Trends): ${seasonalitySummary} FASTEST GROWING LINES (Year-over-Year): ${growthSummary} DECLINING LINES (Year-over-Year): ${declineSummary} TOP PRODUCT LINES (Revenue & Units): ${topLinesSummary} PERFORMANCE BY CUSTOMER: ${customerSummary} `; const response = await ai.models.generateContent({ model: 'gemini-2.5-flash', contents: `Context Data:\n${fullReport}\n\nUser Question: ${question}`, config: { systemInstruction: SYSTEM_INSTRUCTION, } }); return response.text || "I couldn't generate a response based on the data provided."; } catch (error: any) { console.error("Gemini API Error:", error); if (error.message && error.message.includes("Not implemented on this platform")) { return "System Error: The AI SDK detected a platform mismatch."; } return `Error: ${error.message || "An unexpected error occurred while analyzing the data."}`; } };