import { WorkoutSession, UserProfile, WorkoutPlan } from '../types'; import { api } from './api'; interface FitnessChatOptions { history: WorkoutSession[]; userProfile?: UserProfile; plans?: WorkoutPlan[]; lang?: 'en' | 'ru'; sessionId?: string; } export const createFitnessChat = ( history: WorkoutSession[], lang: 'en' | 'ru' = 'ru', userProfile?: UserProfile, plans?: WorkoutPlan[] ): any => { // Generate a unique session ID for this chat instance const sessionId = crypto.randomUUID(); // Summarize workout history const workoutSummary = history.slice(0, 20).map(s => ({ date: new Date(s.startTime).toLocaleDateString(lang === 'ru' ? 'ru-RU' : 'en-US'), userWeight: s.userBodyWeight, planName: s.planName, exercises: s.sets.map(set => { const parts = []; parts.push(set.exerciseName); if (set.weight) parts.push(`${set.weight}${lang === 'ru' ? 'кг' : 'kg'}`); if (set.reps) parts.push(`${set.reps}${lang === 'ru' ? 'повт' : 'reps'}`); if (set.distanceMeters) parts.push(`${set.distanceMeters}${lang === 'ru' ? 'м' : 'm'}`); if (set.durationSeconds) parts.push(`${set.durationSeconds}${lang === 'ru' ? 'сек' : 's'}`); return parts.join(' '); }).join(', ') })); // Calculate personal records const exerciseRecords = new Map(); history.forEach(session => { session.sets.forEach(set => { const current = exerciseRecords.get(set.exerciseName) || {}; exerciseRecords.set(set.exerciseName, { maxWeight: Math.max(current.maxWeight || 0, set.weight || 0), maxReps: Math.max(current.maxReps || 0, set.reps || 0), maxDistance: Math.max(current.maxDistance || 0, set.distanceMeters || 0) }); }); }); const personalRecords = Array.from(exerciseRecords.entries()).map(([name, records]) => ({ exercise: name, ...records })); // Build comprehensive system instruction const systemInstruction = lang === 'ru' ? ` Ты — опытный и поддерживающий фитнес-тренер AI Coach. Твоя задача — анализировать тренировки пользователя и давать краткие, полезные советы на русском языке. ДАННЫЕ ПОЛЬЗОВАТЕЛЯ: ${userProfile ? ` - Вес: ${userProfile.weight || 'не указан'} кг - Рост: ${userProfile.height || 'не указан'} см - Пол: ${userProfile.gender || 'не указан'} ` : 'Профиль не заполнен'} ТРЕНИРОВОЧНЫЕ ПЛАНЫ: ${plans && plans.length > 0 ? JSON.stringify(plans.map(p => ({ name: p.name, exercises: p.steps.map(s => s.exerciseName) }))) : 'Нет активных планов'} ИСТОРИЯ ТРЕНИРОВОК (последние 20): ${JSON.stringify(workoutSummary, null, 2)} ЛИЧНЫЕ РЕКОРДЫ: ${JSON.stringify(personalRecords, null, 2)} ИНСТРУКЦИИ: - Используй эти данные для анализа прогресса и ответов на вопросы - Учитывай вес пользователя при анализе упражнений с собственным весом - Будь конкретным и ссылайся на реальные данные из истории - Отвечай емко, мотивирующе - Если данных недостаточно для ответа, честно скажи об этом ` : ` You are an experienced and supportive fitness coach called AI Coach. Your task is to analyze the user's workouts and provide concise, helpful advice in English. USER PROFILE: ${userProfile ? ` - Weight: ${userProfile.weight || 'not specified'} kg - Height: ${userProfile.height || 'not specified'} cm - Gender: ${userProfile.gender || 'not specified'} ` : 'Profile not filled'} WORKOUT PLANS: ${plans && plans.length > 0 ? JSON.stringify(plans.map(p => ({ name: p.name, exercises: p.steps.map(s => s.exerciseName) }))) : 'No active plans'} WORKOUT HISTORY (last 20 sessions): ${JSON.stringify(workoutSummary, null, 2)} PERSONAL RECORDS: ${JSON.stringify(personalRecords, null, 2)} INSTRUCTIONS: - Use this data to analyze progress and answer questions - Consider user's weight when analyzing bodyweight exercises - Be specific and reference actual data from the history - Answer concisely and motivationally - If there's insufficient data to answer, be honest about it - ALWAYS answer in the language the user speaks to you `; return { sendMessage: async (userMessage: string) => { const res = await api.post('/ai/chat', { systemInstruction, userMessage, sessionId }); return { text: res.response, response: { text: () => res.response } }; } }; };