o
    œŠŽjT  ã                ,   @   s  d dl Z d dlZd dlZd dlmZ d dlmZmZmZm	Z	m
Z
mZmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZmZ d d
lmZ d dlmZ d dlmZmZ d dl m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z( d dl)m*Z*m+Z+ d dl,m,Z, eƒ  eee  -dd¡d�Z.edd�Z/e.e/j0_.e/ 1ee¡ e/j2edgddgdgd� edd�Z3e3j4ddd� edd�Z5e5j4ddd� e*e3ƒZ6e+e5ƒZ7de8d e8fd!d"„Z9d#e8d e8fd$d%„Z:dgd'e;d(e8d)e8d e;fd*d+„Z<d,ed e8fd-d.„Z=e/j>d/e'd0�e. ?d1¡ed2ƒed2ƒed2ƒedƒedƒedƒed3ƒed3ƒed3ƒed4ƒedd d5d6�fd,ed7e8de8d8e8d9ee@ d:eeA d;eeA d<e8d=e8d>e8d?ee8 d@eeA fdAdB„ƒƒZBe/jCdCdDdEge!dF�e. ?dG¡ed2ƒed2ƒed2ƒedƒedƒedƒed3ƒed3ƒed3ƒedƒedƒedƒedƒedƒedƒedƒedƒedƒed4ƒfd,ed7e8de8d8e8d9ee@ d:eeA d;eeA d<e8d=e8d>e8dHee8 dIee@ dJeeA dKeeA dLeeA dMee@ dNee@ dOee@ dPeDd?ee8 f(dQdR„ƒƒZEe/j>dSe#d0�e. ?dT¡ed2ƒed2ƒed2ƒed2ƒed2ƒed2ƒed3ƒed3ƒed3ƒedƒf
d,ed7e8de8d8e8dUe8d#e8dVe@d<e8d=e8d>e8dPeDfdWdX„ƒƒZFe/jGdYe%d0�e. ?dT¡d,edZe$fd[d\„ƒƒZHe/jGd]e&d0�e. ?dG¡ed2ƒed2ƒed2ƒed3ƒed3ƒed3ƒedƒed2ƒfd,ed7e8de8d8e8d<e8d>e8d=e8dHee8 d^e
fd_d`„ƒƒZIe/ >da¡d,efdbdc„ƒZJe/ >dd¡d,efdedf„ƒZKdS )hé    N)ÚOptional)ÚFastAPIÚQueryÚRequestÚHTTPExceptionÚ
UploadFileÚFileÚForm)ÚJSONResponse)ÚCORSMiddleware)Úload_dotenv)ÚImage)Údatetime)ÚLimiterÚ_rate_limit_exceeded_handler)Úget_remote_address)ÚRateLimitExceeded)ÚMealGenVectorStoreÚScannerVectorStore)ÚMealPlanResponseÚSwapMealRequestÚSwapMealResponseÚMealImageRequestÚMealImageResponseÚFoodScanResponseÚDailyNutritionResponseÚMacronutrients)ÚEnhancedMealPlanGeneratorÚFoodScanner)Útranslation_serviceÚ	REDIS_URLzredis://localhost:6379)Úkey_funcÚstorage_uriz+BloodFIT Meal Plan Generator - Scalable API)ÚtitleÚ*T)Úallow_originsÚallow_credentialsÚallow_methodsÚallow_headersÚfaiss_mealgen)Ú
index_pathz'diet/meal_generation/mealgen_foods.jsonF)Úforce_rebuildÚfaiss_scannerz$diet/meal_scanner/scanner_foods.jsonÚ
blood_typeÚreturnc                 C   s$   |   ¡  ¡ } |  d¡d  d¡d S )Nú+r   ú-)ÚstripÚupperÚsplit)r-   © r4   úL/home/esfera/Desktop/Rishu/fitness/Fitness-lenito-AI-main/fitness_app/app.pyÚnormalize_blood_type7   s   r6   Úsub_categoryc                 C   s:   |   ¡  ¡ } dddddddœ}| | |  dd¡ dd¡¡S )NÚprotein_packedÚlight_freshÚhealthy_comforting)zprotein-packedzprotein packedzlight & freshzlight and freshzhealthy & comfortingzhealthy and comfortingú Ú_r0   )Úlowerr1   ÚgetÚreplace)r7   Úmappingr4   r4   r5   Únormalize_sub_category;   s   úrA   Ú	meal_planÚresponse_dataÚlanguageÚresponse_typec                    sn   ˆ dkst  ¡ s
| S |dkrt  | ˆ ¡S |dkrt  | ˆ ¡S |dkr5‡ fdd„|  dg ¡D ƒ}|| d< | S | S )NÚenrB   Ú	food_scanÚ	swap_mealc                    s   g | ]}t  |ˆ ¡‘qS r4   )r   Útranslate_meal)Ú.0Úmeal©rD   r4   r5   Ú
<listcomp>O   s    
ÿÿz&translate_response.<locals>.<listcomp>Úalternatives)r   Úis_translation_enabledÚtranslate_meal_plan_responseÚtranslate_food_scan_responser>   )rC   rD   rE   Útranslated_alternativesr4   rL   r5   Útranslate_responseG   s   

þrS   Úrequestc                 C   s   | j  dd¡S )NrD   rF   )Úquery_paramsr>   )rT   r4   r4   r5   Úget_language_from_requestW   s   rV   z/calculate-daily-nutrition)Úresponse_modelz	20/minute.Ú zStay Fiti,  )ÚgtÚleÚuser_idÚ	diet_typeÚageÚweightÚheightÚcountryÚfood_dislikesÚ	allergiesÚ	main_goalÚdesired_weightc                 Ã   s®   �t | ƒ}t|ƒ}| ¡ }g d¢}g d¢}||vr'd}|dkr!d}td|d�‚||vr9d}|dkr3d	}td|d�‚|d
kr?d}|||||||||	|
|dœ}t |¡I d H }|S )N©ÚOÚAÚBÚAB©ÚclassicÚveganÚpescatarianÚ
vegetarianú+Invalid blood type. Must be O, A, B, or AB.ÚkoõE   ìž˜ëª»ë�œ í˜ˆì•¡í˜•ìž…ë‹ˆë‹¤. O, A, B, AB ì¤‘ í•˜ë‚˜ì—¬ì•¼ í•©ë‹ˆë‹¤.é�  ©Ústatus_codeÚdetailúGInvalid diet type. Must be classic, vegan, pescatarian,  or vegetarian.õy   ìž˜ëª»ë�œ ì‹�ë‹¨ ìœ í˜•ìž…ë‹ˆë‹¤. í�´ëž˜ì‹�, ë¹„ê±´, íŽ˜ìŠ¤ì¹´í…Œë¦¬ì•ˆ, ì¹´ë‹ˆë³´ì–´, ë¹„ê±´ ì¤‘ í•˜ë‚˜ì—¬ì•¼ í•©ë‹ˆë‹¤.rk   Ústandard)r[   r-   r\   r]   r^   r_   r`   ra   rb   rc   rd   )rV   r6   r=   r   Úmeal_generatorÚcalculate_daily_nutrition)rT   r[   r-   r\   r]   r^   r_   r`   ra   rb   rc   rd   rD   Úvalid_blood_typesÚvalid_diet_typesÚ	error_msgÚ	user_dataÚnutrition_responser4   r4   r5   rz   ^   s@   €õrz   z/generate-meal-planÚGETÚPOST)ÚmethodsrW   z	10/minuteÚblood_group_rulesÚtotal_daily_caloriesÚcarbsÚproteinÚfatÚbreakfast_caloriesÚlunch_caloriesÚdinner_caloriesÚgenerate_imagesc                  Ã   sÄ  �t | ƒ}t|ƒ}| ¡ }|
s.| jdkr.z|  ¡ I d H }| d¡p"d }
W n	 ty-   Y nw g d¢}g d¢}||vrHd}|dkrBd}td|d	�‚||vrZd
}|dkrTd}td|d	�‚|dkr`d}|||||||||	|
|dœ}d }|r¢|r¢|r¢|r¢i }|r€||d< |r†||d< |rŒ||d< t|t	|||d�|||t
 ¡ |rž|nd d�}ztj|||d�I d H }| ¡ }t||dƒ}t|d�W S  tyá } zdt|ƒ› �}|dkr×dt|ƒ› �}td|d	�‚d }~ww )Nr�   rƒ   re   rj   ro   rp   rq   rr   rs   rv   rw   rk   rx   )r[   r-   r\   r]   r^   r_   r`   ra   rb   rƒ   rc   Ú	breakfastÚlunchÚdinner)Úcarbohydratesr†   r‡   )r„   Útotal_daily_macronutrientsr[   r-   r\   Úcalculation_timestampÚmeal_calorie_distribution©r‹   rB   ©ÚcontentzMeal plan generation failed: u   ì‹�ë‹¨ ê³„íš� ìƒ�ì„± ì‹¤íŒ¨: éô  )rV   r6   r=   ÚmethodÚformr>   Ú	Exceptionr   r   r   r   Únowry   Úgenerate_meal_planÚdictrS   r
   Ústr) rT   r[   r-   r\   r]   r^   r_   r`   ra   rb   rƒ   r„   r…   r†   r‡   rˆ   r‰   rŠ   r‹   rc   rD   r˜   r{   r|   r}   r~   Údaily_nutritionÚmeal_distributionÚmeal_plan_responseÚresponse_dictÚtranslated_responseÚer4   r4   r5   r›   –   s˜   €
ÿõý
õý€ür›   z
/swap-mealz	15/minuteÚcategoryÚcurrent_caloriesc                 Ã   s&  �t | ƒ}t|ƒ}| ¡ }| ¡ }t|ƒ}g d¢}g d¢}||vr/d}|dkr)d}td|d�‚||vrAd}|dkr;d	}td|d�‚|d
krGd}t|||||||||	d�	}ztj||
d�I d H }| ¡ }t	||dƒ}t
|d�W S  ty’ } zdt|ƒ› �}|dkrˆdt|ƒ› �}td|d�‚d }~ww )Nre   rj   ro   rp   rq   rr   rs   rv   rw   rk   rx   )	r[   r-   r\   r¤   r7   r¥   r`   ra   rb   r“   rH   r”   zSwap meal generation failed: u   ëŒ€ì²´ ì‹�ì‚¬ ìƒ�ì„± ì‹¤íŒ¨: r–   )rV   r6   r=   rA   r   r   ry   Úgenerate_swap_mealsrœ   rS   r
   r™   r�   )rT   r[   r-   r\   r¤   r7   r¥   r`   ra   rb   r‹   rD   r{   r|   r}   Úswap_requestÚswap_responser¡   r¢   r£   r4   r4   r5   rH     sV   €÷€ürH   z/generate-meal-imagesÚmeal_requestc              
   Ã   s�   �zt | ƒ}dd„ |jD ƒ}tj |j|j|¡}t||jd�W S  t	yG } zdt
|ƒ› �}t | ƒ}|dkr=dt
|ƒ› �}td|d�‚d }~ww )	Nc                 S   s   g | ]}|j |jp
d dœ‘qS )Úsome©ÚnameÚquantityr«   )rJ   Úingr4   r4   r5   rM   N  s    ÿÿz(generate_meal_images.<locals>.<listcomp>)Úmeal_image_base64ÚidzImage generation failed: rp   u   ì�´ë¯¸ì§€ ìƒ�ì„± ì‹¤íŒ¨: r–   rs   )rV   Úingredientsry   Úmeal_image_generatorÚgenerate_meal_imageÚ	meal_nameÚdescriptionr   r°   r™   r�   r   )rT   r©   rD   Úingredients_listr¯   r£   r}   r4   r4   r5   Úgenerate_meal_imagesF  s.   €þýþ€ûr·   z
/scan-foodÚimagec	              
   Ã   s\  �t | ƒ}	t|ƒ}| ¡ }|s| j d¡pd }g d¢}
g d¢}||
vr1d}|	dkr+d}td|d�‚||vrCd	}|	dkr=d
}td|d�‚|dkrId}|j d¡s]d}|	dkrWd}td|d�‚z[| ¡ I d H }zt	 
t |¡¡}| ¡  W n tyˆ   d}|	dkr‚d}td|d�‚w t	 
t |¡¡}|jdk s›|jdk r©d}|	dkr£d}td|d�‚|jdkr³| d¡}| ¡  W n+ tyÀ   ‚  tyã } zdt|ƒ› �}|	dkrÙdt|ƒ› �}td|d�‚d }~ww |||||||dœ}zt ||¡I d H }| ¡ }t||	dƒ}t|d�W S  t�y- } zdt|ƒ› �}|	dk�r#dt|ƒ› �}td|d�‚d }~ww )Nrƒ   re   rj   ro   rp   rq   rr   rs   rv   rw   rk   rx   zimage/zFile must be an imageu#   íŒŒì�¼ì�€ ì�´ë¯¸ì§€ì—¬ì•¼ í•©ë‹ˆë‹¤zInvalid image fileu#   ìž˜ëª»ë�œ ì�´ë¯¸ì§€ íŒŒì�¼ìž…ë‹ˆë‹¤éd   z1Image too small. Minimum 100x100 pixels required.uK   ì�´ë¯¸ì§€ê°€ ë„ˆë¬´ ìž‘ìŠµë‹ˆë‹¤. ìµœì†Œ 100x100 í”½ì…€ì�´ í•„ìš”í•©ë‹ˆë‹¤.ÚRGBzError processing image: u   ì�´ë¯¸ì§€ ì²˜ë¦¬ ì˜¤ë¥˜: )r[   r-   r\   r`   ra   rb   rƒ   rG   r”   zFood scanning failed: u   ì�Œì‹� ìŠ¤ìº” ì‹¤íŒ¨: r–   )rV   r6   r=   rU   r>   r   Úcontent_typeÚ
startswithÚreadr   ÚopenÚioÚBytesIOÚverifyr™   Úwidthr_   ÚmodeÚconvertÚcloser�   Úfood_scannerÚscan_food_imagerœ   rS   r
   )rT   r[   r-   r\   r`   rb   ra   rƒ   r¸   rD   r{   r|   r}   Ú
image_dataÚimgr£   r~   Úscan_responser¡   r¢   r4   r4   r5   Ú	scan_foodg  s”   €ü

€üù

€ürË   z/healthc                 Ã   sv   �t | ƒ}tjdu}|rttjjƒnd}|rdnd}|dkr$|r"dnd}|d|||d	g d
¢dddddddœt ¡ dœ
S )u6   Health check endpoint â€“ now uses vector store stats.Nr   ÚhealthyÚdegradedrp   u   ì •ìƒ�u	   ì €í•˜ë�¨úBloodFIT Meal Plan APIõA   9 meals per category (3 per subâ€‘category Ã— 3 subâ€‘categories)©zProtein-PackedzLight & FreshzHealthy & Comfortingé   z0Calculate daily nutrition with meal distributionu*   Generate 27â€‘meal plan with new structureu&   Swap meals with subâ€‘category supportzScan food imagesúGenerate meal images)z/meal/calculate-daily-nutritionz/meal/generate-meal-planz/meal/swap-mealz/meal/scan-foodz/meal/generate-meal-images)
ÚstatusÚservicerD   Úvector_store_loadedÚtotal_document_chunksÚnew_structureÚsub_categoriesÚtotal_meals_per_planÚ	endpointsÚtranslation_enabled)rV   Ú
meal_storeÚvectorstoreÚlenÚindex_to_docstore_idr   rO   )rT   rD   Úindex_loadedÚ	doc_countÚstatus_messager4   r4   r5   Úhealth_checkÌ  s.   €
ûðrã   ú/c                 Ã   sb   �t | ƒ}|dkrdddg d¢dddd	d
ddœg d¢dœS dddg d¢dddddddœg d¢dœS )zAPI Documentationrp   u   BloodFIT ì‹�ë‹¨ ê³„íš� APIz3.0 (Vector Store)u`   ê°� ì¹´í…Œê³ ë¦¬ë‹¹ 9ê°œ ì‹�ì‚¬ ì˜µì…˜ (í•˜ìœ„ ì¹´í…Œê³ ë¦¬ë‹¹ 3ê°œ Ã— 3ê°œ í•˜ìœ„ ì¹´í…Œê³ ë¦¬))u   ë‹¨ë°±ì§ˆ í’�ë¶€u   ê°€ë³�ê³  ì‹ ì„ í•¨u   ê±´ê°•í•˜ê³  íŽ¸ì•ˆí•¨rÑ   u   ì�¼ì�¼ ì˜�ì–‘ì†Œ ëª©í‘œ ê³„ì‚°u(   ìƒˆë¡œìš´ êµ¬ì¡°ë¡œ ì‹�ë‹¨ ê³„íš� ìƒ�ì„±u8   ë�™ì�¼í•œ í•˜ìœ„ ì¹´í…Œê³ ë¦¬ì—�ì„œ ëŒ€ì²´ ì‹�ì‚¬ ìƒ�ì„±u   ì�Œì‹� ì�´ë¯¸ì§€ ìŠ¤ìº”u   ì‹�ì‚¬ ì�´ë¯¸ì§€ ìƒ�ì„±)z#GET /meal/calculate-daily-nutritionzGET /meal/generate-meal-planzGET /meal/swap-mealzPOST /meal/scan-foodzPOST /meal/generate-meal-images)uN   1. /meal/calculate-daily-nutrition í˜¸ì¶œí•˜ì—¬ ì�¼ì�¼ ì˜�ì–‘ì†Œ ëª©í‘œ ê³„ì‚°uF   2. ê²°ê³¼ë¥¼ /meal/generate-meal-planì—� ì¿¼ë¦¬ ë§¤ê°œë³€ìˆ˜ë¡œ ì „ë‹¬uD   3. ë˜�ëŠ” /meal/generate-meal-plan ì§�ì ‘ í˜¸ì¶œí•˜ì—¬ ìž�ë�™ ê³„ì‚°)ÚmessageÚversionu   êµ¬ì¡°u   í•˜ìœ„_ì¹´í…Œê³ ë¦¬u   ì´�_ì‹�ì‚¬_ì˜µì…˜u   ì—”ë“œí�¬ì�¸íŠ¸u	   ì‚¬ìš©ë²•rÎ   rÏ   rÐ   z!Calculate daily nutrition targetsz%Generate meal plan with new structureu5   Generate alternative meals within same subâ€‘categoryz'Scan food image for harmful ingredientsrÒ   )zF1. Call /meal/calculate-daily-nutrition to get daily nutrition targetszF2. Pass the results to /meal/generate-meal-plan using query parameterszF3. Or call /meal/generate-meal-plan directly for automatic calculation)rå   ræ   Ú	structurerØ   Útotal_meal_optionsrÚ   Ú
usage_flow)rV   )rT   rD   r4   r4   r5   Úhomeí  s:   €ûóûórê   )rB   )LÚosr¿   ÚuvicornÚtypingr   Úfastapir   r   r   r   r   r   r	   Úfastapi.responsesr
   Úfastapi.middleware.corsr   Údotenvr   ÚPILr   r   Úslowapir   r   Úslowapi.utilr   Úslowapi.errorsr   Úfitness_app.vector_storer   r   Úfitness_app.data_managerr   r   r   r   r   r   r   r   Úfitness_app.ai_servicesr   r   r   ÚgetenvÚlimiterÚappÚstateÚadd_exception_handlerÚadd_middlewarerÜ   Úload_or_create_indexÚscanner_storery   rÆ   r�   r6   rA   rœ   rS   rV   r>   ÚlimitÚintÚfloatrz   Ú	api_routeÚboolr›   rH   Úpostr·   rË   rã   rê   r4   r4   r4   r5   Ú<module>   s¬   $(
û

ôÿþýüûúùø	÷
öõô6ìÿþýüûúùø	÷
öõôóòñðïîíìmõÿþýüûúùø	÷
öõ?ÿþ÷ÿþýüûúùø	÷c 