import { cache } from 'react'; import { AccountWithParams } from '@/packages/features/accounts/src/types/accounts'; import { createUserAnalysesApi } from '@/packages/features/user-analyses/src/server/api'; import { getSupabaseServerClient } from '@/packages/supabase/src/clients/server-client'; import { Database } from '@/packages/supabase/src/database.types'; import OpenAI from 'openai'; import PersonalCode from '~/lib/utils'; import { OrderAnalysisCard } from '../../_components/order-analyses-cards'; export const loadRecommendations = cache(recommendationsLoader); type AnalysisResponses = Database['medreport']['Functions']['get_latest_analysis_response_elements_for_current_user']['Returns']; const getLatestResponseTime = (items: AnalysisResponses) => { if (!items?.length) return null; let latest = null; for (const it of items) { const d = new Date(it.response_time); const t = d.getTime(); if (!Number.isNaN(t) && (latest === null || t > latest.getTime())) { latest = d; } } return latest; }; async function recommendationsLoader( analyses: OrderAnalysisCard[], account: AccountWithParams | null, ): Promise { if (!process.env.OPENAI_API_KEY) { return []; } if (!account?.personal_code) { return []; } const supabaseClient = getSupabaseServerClient(); const userAnalysesApi = createUserAnalysesApi(supabaseClient); const analysisResponses = await userAnalysesApi.getAllUserAnalysisResponses(); const analysesRecommendationsPromptId = process.env.PROMPT_ID_ANALYSIS_RECOMMENDATIONS; const latestResponseTime = getLatestResponseTime(analysisResponses); const latestISO = latestResponseTime ? new Date(latestResponseTime).toISOString() : new Date('2025').toISOString(); if (!analysesRecommendationsPromptId) { console.error('No prompt ID for analysis recommendations'); return []; } const previouslyRecommended = await supabaseClient .schema('medreport') .from('ai_responses') .select('*') .eq('account_id', account.id) .eq('prompt_id', analysesRecommendationsPromptId) .eq('latest_data_change', latestISO); if (previouslyRecommended.data?.[0]?.response) { return JSON.parse(previouslyRecommended.data[0].response as string) .recommended; } const openAIClient = new OpenAI(); const { gender, age } = PersonalCode.parsePersonalCode(account.personal_code); const weight = account.accountParams?.weight || 'unknown'; const formattedAnalysisResponses = analysisResponses.map( ({ analysis_name_lab, response_value, norm_upper, norm_lower, norm_status, }) => ({ name: analysis_name_lab, value: response_value, normUpper: norm_upper, normLower: norm_lower, normStatus: norm_status, }), ); const formattedAnalyses = analyses.map(({ description, title }) => ({ description, title, })); let response; try { response = await openAIClient.responses.create({ store: false, prompt: { id: analysesRecommendationsPromptId, variables: { analyses: JSON.stringify(formattedAnalyses), results: JSON.stringify(formattedAnalysisResponses), gender: gender.value, age: age.toString(), weight: weight.toString(), }, }, }); } catch (error) { console.error('Error calling OpenAI: ', error); return []; } const json = JSON.parse(response.output_text); try { await supabaseClient .schema('medreport') .from('ai_responses') .insert({ account_id: account.id, prompt_name: 'Analysis Recommendations', prompt_id: analysesRecommendationsPromptId, input: JSON.stringify({ analyses: formattedAnalyses, results: formattedAnalysisResponses, gender, age, weight, }), latest_data_change: latestISO, response: response.output_text, }); } catch (error) { console.error('Error saving AI response: ', error); } return json.recommended; }