
    h(oig                         d Z ddlZddlmZmZ ddlmZ ddlmZmZ ddl	m
Z
 ddlmZmZmZmZmZ ddlmZ  ee          Z G d	 d
          ZdS )z|
Storage service for manual health logs.

Handles reading/writing user-entered diet, alcohol, supplement, and feeling data.
    N)datedatetime)Path)OptionalList)config)DailyManualLog	DietEntryAlcoholEntrySupplementEntryBodyFeelingEntry)setup_loggerc                       e Zd ZdZddee         ddfdZddededefd	Z	dede
fd
Zde
defdZdedede
fdZdedede
fdZdedede
fdZdedede
fdZdedede
fdZdededee
         fdZdS )ManualLogStoragez6Service for storing and retrieving manual health logs.Ndata_dirreturnc                     |pt           j        | _        | j        dz  | _        | j                            dd           dS )zInitialize manual log storage service.

        Args:
            data_dir: Optional data directory path (defaults to config.DATA_DIR)
        manual_logsTparentsexist_okN)r   DATA_DIRr   manual_log_dirmkdir)selfr   s     ;/root/projects/butler/health/services/manual_log_storage.py__init__zManualLogStorage.__init__   sC     !3FO"mm;!!$!>>>>>    Ttarget_datecreate_dirsc                     t          |j                  }|j        d}|                                 d}| j        |z  |z  |z  }|r|j                            dd           |S )a  Get file path for a manual log.

        Args:
            target_date: Date of the log
            create_dirs: Whether to create directories if they don't exist

        Returns:
            Full path to JSON file (data/health/manual_logs/YYYY/MM/YYYY-MM-DD.json)
        02dz.jsonTr   )stryearmonth	isoformatr   parentr   )r   r   r    r$   r%   filename	file_paths          r   _get_file_pathzManualLogStorage._get_file_path&   s~     ;#$$$**!++--444'$.6A	 	@""4$"???r   c                    |                      |d          }|                                s.t                              d| d           t	          |          S 	 t          |dd          5 }t          j        |          }d	d	d	           n# 1 swxY w Y   t	          di |}t                              d
|            |S # t          $ r:}t          	                    d| d|            t	          |          cY d	}~S d	}~ww xY w)zLoad manual log for a specific date.

        Args:
            target_date: Date to load

        Returns:
            DailyManualLog instance (creates new if doesn't exist)
        F)r    zNo manual log found for z, creating new)log_daterutf-8encodingNzLoaded manual log for zFailed to load manual log for :  )
r*   existsloggerdebugr	   openjsonload	Exceptionerror)r   r   r)   fdataloges          r   load_logzManualLogStorage.load_log;   so    '''GG	!! 	8LLOKOOOPPP!;7777	8iw777 $1y||$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ !((4((CLL?+??@@@J 	8 	8 	8LLL+LLLLMMM!;777777777	8sB   C -BC BC B-C 
D/D=DDr=   c                    	 t          j                    |_        |                     |j                  }|                    d          }t          |dd          5 }t          j        ||dd           d	d	d	           n# 1 swxY w Y   t          
                    d
|j         d|            |S # t          $ r+}t                              d|j         d|             d	}~ww xY w)zSave manual log to JSON file.

        Args:
            log: DailyManualLog instance to save

        Returns:
            Path to saved file
        r7   )modewr.   r/      F)indentensure_asciiNzSaved manual log for z to zFailed to save manual log for r1   )r   now
updated_atr*   r,   
model_dumpr6   r7   dumpr4   infor9   r:   )r   r=   r)   	data_dictr;   r>   s         r   save_logzManualLogStorage.save_logX   sB   	%\^^CN++CL99I F33Iiw777 F1	)QquEEEEF F F F F F F F F F F F F F F KKMMM)MMNNN 	 	 	LLM#,MM!MMNNN	s<   AB3 B5B3 BB3 B	)B3 3
C(=&C##C(entryc                     |                      |          }|j                            |           |                     |           t                              d| d|j                    |S )zAdd a diet entry to the log.

        Args:
            target_date: Date of the entry
            entry: DietEntry to add

        Returns:
            Updated DailyManualLog
        zAdded diet entry for  at )r?   diet_entriesappendrL   r4   rJ   timer   r   rM   r=   s       r   add_diet_entryzManualLogStorage.add_diet_entryt   sh     mmK((&&&cIKIIUZIIJJJ
r   c                     |                      |          }|j                            |           |                     |           t                              d| d|j                    |S )zAdd an alcohol entry to the log.

        Args:
            target_date: Date of the entry
            entry: AlcoholEntry to add

        Returns:
            Updated DailyManualLog
        zAdded alcohol entry for rO   )r?   alcohol_entriesrQ   rL   r4   rJ   rR   rS   s       r   add_alcohol_entryz"ManualLogStorage.add_alcohol_entry   sh     mmK((""5)))cL{LL
LLMMM
r   c                     |                      |          }|j                            |           |                     |           t                              d| d|j                    |S )zAdd a supplement entry to the log.

        Args:
            target_date: Date of the entry
            entry: SupplementEntry to add

        Returns:
            Updated DailyManualLog
        zAdded supplement entry for r1   )r?   supplement_entriesrQ   rL   r4   rJ   supplement_namerS   s       r   add_supplement_entryz%ManualLogStorage.add_supplement_entry   si     mmK((%%e,,,cX+XXAVXXYYY
r   c                     |                      |          }|j                            |           |                     |           t                              d| d|j                    |S )zAdd a body feeling entry to the log.

        Args:
            target_date: Date of the entry
            entry: BodyFeelingEntry to add

        Returns:
            Updated DailyManualLog
        zAdded feeling entry for r1   )r?   feeling_entriesrQ   rL   r4   rJ   feeling_typerS   s       r   add_feeling_entryz"ManualLogStorage.add_feeling_entry   si     mmK((""5)))cR{RRe>PRRSSS
r   rA   c                     |                      |          }||_        |                     |           t                              d| d|            |S )zSet the fasting mode for a day.

        Args:
            target_date: Date to set
            mode: Fasting mode (PSMF/OMAD/Water Fast/Normal)

        Returns:
            Updated DailyManualLog
        zSet fasting mode for r1   )r?   fasting_moderL   r4   rJ   )r   r   rA   r=   s       r   set_fasting_modez!ManualLogStorage.set_fasting_mode   sW     mmK((cAKAA4AABBB
r   
start_dateend_datec                     g }|}||k    rh|                      |          }|j        s|j        s|j        s|j        s|j        r|                    |           ddlm} | |d          z  }||k    h|S )zGet all manual logs in a date range.

        Args:
            start_date: Start date (inclusive)
            end_date: End date (inclusive)

        Returns:
            List of DailyManualLog instances
        r   )	timedelta   )days)	r?   rP   rV   rY   r]   ra   rQ   r   rf   )r   rc   rd   logscurrent_dater=   rf   s          r   get_logs_in_rangez"ManualLogStorage.get_logs_in_range   s     !h&&----C  !&! )! &	!
 #! C    +*****II1----L h&&  r   )N)T)__name__
__module____qualname____doc__r   r   r   r   boolr*   r	   r?   rL   r
   rT   r   rW   r   r[   r   r_   r#   rb   r   rk   r2   r   r   r   r      s       @@? ?$ ?4 ? ? ? ? $ T T    *8D 8^ 8 8 8 8:N t    8(1	   $(4	   $(7	   $(8	   $D       *.	n	     r   r   )ro   r7   r   r   pathlibr   typingr   r   healthr   health.models.manual_logr	   r
   r   r   r   health.utils.logging_configr   rl   r4   r   r2   r   r   <module>rv      s     # # # # # # # #       ! ! ! ! ! ! ! !                    5 4 4 4 4 4	h		R R R R R R R R R Rr   