
    mi$                     Z   d Z ddlZddlmZmZ ddlmZ ddl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mZ  ee          Z ej                    d1d            Ze                                d1d            Ze                                 ej        ddedd           ej        dddd          deded
dfd                                    Ze                                 ej        dddd           ej        dddd !           ej        d"d#ee	j        d$e	j         d%           ej        d&d'dd()          d*ed+ee         d,ed-e d
df
d.                                                            Z!e                                d1d/            Z"ed0k    r e             dS dS )2aP  
CLI tool for Garmin health data synchronization.

Usage:
    python -m health.cli.sync status           # Show sync status
    python -m health.cli.sync sync-now         # Sync today
    python -m health.cli.sync sync --days 7    # Sync last 7 days
    python -m health.cli.sync backfill --start-date 2024-01-01  # Historical backfill
    N)date	timedelta)Optional)config)HealthDataSync)
parse_dateget_yesterday)setup_logger)GarminAuthError	SyncErrorreturnc                      dS )zGarmin Health Data Sync CLI.N r       (/root/projects/butler/health/cli/sync.pyclir      s	     	Dr   c                  v   t          j        d           t                      } |                                 }g }g }|                                D ]>\  }}|d         dk    r|                    ||f           )|                    |           ?|r}t          j        d           |D ]f\  }}t          j                            |i                               dd          }t          j        d|dd	|d
          d|d          d|            g|rht          j        d           |D ]Q}t          j                            |i                               dd          }t          j        d|dd|            Rt          j        dt          j	                    t          j        dt          j
                    dS )z/Show synchronization status for all data types.u   📊 Health Data Sync Status
statussyncedu   ✅ Synced Data Types:description u     • 20z Last sync: last_sync_datez  (total_recordsz records) - u   
⚠️  Never Synced: u   
📁 Data directory: u   🗄️  Database: N)clickechor   get_sync_statusitemsappendr   DATA_TYPE_CONFIGgetDATA_DIRDB_PATH)sync_servicestatus_infor   never_synced	data_typeinfor   s          r   r   r       s    
J/000!##L..00K FL&,,.. + +	4>X%%MM9d+,,,,	****  	
+,,,% 	 	OIt 155iDDHHr K JEM E E48H3I E E)E E7BE E     >
,---% 	> 	>I 155iDDHHr K J<	<<<{<<====	J:::;;;	J5V^5566666r   z--daysz-d   z1Number of days to sync (from yesterday backwards))typedefaulthelpz--forcez-fTzForce re-sync existing data)is_flagr-   daysforcec                    	 t                      }|t          | dz
            z
  }t          j        d| d|            |rt          j        d           t	                      }t          j        d           |                                 t          j        d           |                    |||          }t          j        d	           d
}d
}|                                D ]\  }}	|	                    dd
          }
|	                    dd
          }|	                    dd
          }||
z  }||z  }|d
k    rdnd}t          j        d| d|dd|
dd|dd|d
           t          j        d|d
k    rdnd d| d| d           t          j
        |d
k    rd
nd           d!S # t          $ rN}t          j        d| d           t          j        d d           t          j
        d           Y d!}~d!S d!}~wt          $ rR}t          j        d"| d           t                              d#           t          j
        d           Y d!}~d!S d!}~ww xY w)$z!Sync health data for recent days.r*   )r/   u   🔄 Syncing health data from z to z)   (Force mode: re-syncing existing data)u0   🔐 Authenticating with Garmin Connect China...   ✅ Authentication successful
)r0   u   
📊 Sync Results:r   r   skippederrors   ✓   ⚠  r   r   z	 Synced: 3z, Skipped: z
, Errors: 
   ✅   ⚠️  Total: z records synced, z errors   
❌ Authentication failed: Terrz9   Please check your Garmin credentials in the .env file.Nu   
❌ Sync failed: zSync failed)r	   r   r   r   r   authenticatesync_all_metricsr   r"   sysexitr   	Exceptionlogger	exception)r/   r0   end_date
start_dater%   resultstotal_syncedtotal_errorsmetric_typestatsr   r3   r4   status_icones                  r   syncrP   K   s.   9 ??	tax 8 8 88

NJNNHNNOOO 	DJBCCC &'' 	
EFFF!!###
4555 // 0 
 

 	
)***")--// 	 	KYYx++Fii	1--GYYx++FF"LF"L#)Q;;%%EKJP[ P P;4 P P!OP P07OP PEKOP P   
 	
K,!++ K K"K K5AK K K	
 	
 	

 	la''Q/////   
6166DAAAA
GT	
 	
 	
 	
 	   
,,,$7777'''s&   F'F+ +
I5AG>>IAIIz--start-datez-sz$Start date for backfill (YYYY-MM-DD))requiredr-   z
--end-datez-ez-End date for backfill (defaults to yesterday))r,   r-   z--batch-sizez-bzDays per batch (default: )z	--metricsz-mz:Specific metrics to sync (can be specified multiple times))multipler-   rH   rG   
batch_sizemetricsc                    	 t          |           }|rt          |          nt                      }||k    r*t          j        dd           t	          j        d           ||z
  j        dz   }t          j        d           t          j        d|            t          j        d|            t          j        d|            t          j        d	| d
           |r*t          j        dd                    |                      |dk    rt          j        d| dd           t                      }t          j        d           |
                                 t          j        d           |rt          |          nd}|                    ||||          }	t          j        d           t          d |	                                D                       }
t          d |	                                D                       }|	                                D ]n\  }}|                    dd          }|                    dd          }|dk    rdnd}t          j        |rd| d|dd|d d!| d"	nd| d|dd|d d#           ot          j        d$|dk    rd%nd& d'|
 d(           t	          j        |dk    rdnd           dS # t"          $ r8}t          j        d)| d           t	          j        d           Y d}~dS d}~wt$          $ rR}t          j        d*| d           t&                              d+           t	          j        d           Y d}~dS d}~ww xY w),z Backfill historical health data.u&   ❌ Start date must be before end dateTr>   r*   u   📚 Historical Backfillz   Start date: z   End date: z   Total days: z   Batch size: z daysz   Metrics: z, Z   u   
⚠️  This will backfill z days of data. Continue?)abortu1   
🔐 Authenticating with Garmin Connect China...r2   N)metric_typesrT   u   
📊 Backfill Complete!c              3   B   K   | ]}|                     d d          V  dS )r   r   Nr"   .0ss     r   	<genexpr>zbackfill.<locals>.<genexpr>   0      HH!1551--HHHHHHr   c              3   B   K   | ]}|                     d d          V  dS )r4   r   Nr[   r\   s     r   r_   zbackfill.<locals>.<genexpr>   r`   r   r   r   r4   r5   r6   r7   r   r   4z records  ( errors)z recordsr9   r:   r;   r<   z records syncedr=   u   
❌ Backfill failed: zBackfill failed)r   r	   r   r   rB   rC   r/   joinconfirmr   r@   listbackfill_historicalsumvaluesr   r"   r   rD   rE   rF   )rH   rG   rT   rU   startend
total_daysr%   metric_listrI   rJ   rK   rL   rM   r   r4   rN   rO   s                     r   backfillrn      s*   BF:&&&.Cj"""MOO 3;;J?TJJJJHQKKKEk'!+

.///
,U,,---
(3(()))
1Z11222
6Z666777 	<J:dii&8&8::;;; ??MT
TTT    &'' 	
GHHH!!###
4555 (/8d7mmmD223[Z 3 
 

 	
.///HHw~~7G7GHHHHHHHw~~7G7GHHHHH")--// 	 	KYYx++FYYx++F#)Q;;%%EKJ(.k %[ % %;H % %FH % %% % % %4j4j4j{4j4j4jX^4j4j4j4j   
 	
4,!++ 4 4"4 4 4	
 	
 	

 	la''Q/////   
6166DAAAA   
0Q00d;;;;*+++s%   K
K 
M*-LM*AM%%M*c                  >   	 t          j        d           t                      } t          j        d           |                                  t          j        d           |                                 }t          j        d           d}d}|                                D ]\  }}|                    dd          }|                    dd          }|dk    s|dk    rG||z  }||z  }|dk    rdnd	}t          j        |rd
| d|dd|dd| d	nd
| d|dd|dd           |dk    rt          j        d           t          j        d|dk    rdnd d| d           t          j        |dk    rdnd           dS # t          $ r8}	t          j        d|	 d           t          j        d           Y d}	~	dS d}	~	wt          $ rR}	t          j        d|	 d           t                              d           t          j        d           Y d}	~	dS d}	~	ww xY w)z9Perform incremental sync (sync new data since last sync).u.   🔄 Incremental Sync (syncing new data only)
u   🔐 Authenticating...u   ✅ Authenticated
u   📊 Sync Results:r   r   r4   r5   r6   r7   r   r   r8   z new records  (rc   z new recordsu!     ℹ️  All data is up to date!r9   r:   r;   z Synced r*   r=   Tr>   Nu   
❌ Incremental sync failed: zIncremental sync failed)r   r   r   r@   sync_incrementalr   r"   rB   rC   r   rD   rE   rF   )
r%   rI   rJ   rK   rL   rM   r   r4   rN   rO   s
             r   rp   rp      s   1
DEEE &'' 	
+,,,!!###
())) //11 	
'(((")--// 	 	KYYx++FYYx++FzzVaZZ&&'-{{ee
,2s ) ) ){P ) )P ) )) ) ) )8r[8r8r;8r8r8r\b8r8r8r8r  
 1J:;;;
1,!++ 1 1"1 1 1	
 	
 	

 	la''Q/////   
6166DAAAA   
8Q88dCCCC2333s%   E<F   
H
-F==H
AHH__main__)r   N)#__doc__rB   datetimer   r   typingr   r   healthr   health.services.data_syncr   health.utils.date_utilsr   r	   health.utils.logging_configr
   health.utils.exceptionsr   r   __name__rE   groupr   commandr   optionintboolrP   DEFAULT_BATCH_SIZE_DAYSstrtuplern   rp   r   r   r   <module>r      s    


 $ $ $ $ $ $ $ $              4 4 4 4 4 4 = = = = = = = = 4 4 4 4 4 4 > > > > > > > >	h		 	 	 	 	
 '7 '7 '7 '7T 		<   it2OPPP;s ;4 ;D ; ; ; QP  ;| 	/	   	8	   	*	FV%C	F	F	F   	E	  MMsmM M 	M
 
M M M     4M` 3 3 3 3l zCEEEEE r   