o
    pѬiJ                     @   sh   d Z ddlZddlZddlZddlZddlmZmZ ddlmZ e	dZ
G dd dZdadd	 ZdS )
aM  
Google Drive Health Connect connector.

Searches Bill's Google Drive for Health Connect zip files,
downloads the latest one to a temp directory, and hands it
off to the health_connect parser for ingestion.

Primary method: Google Drive API (no dependency on local sync)
Fallback: filesystem watcher (local Google Drive sync folder)
    N)datetime	timedelta)Pathzgdrive-healthc                   @   sX   e Zd ZdZdd Zedd Zedd Zdd	d
ZdddZ	dddZ
dddZdS )GDriveHealthConnectorz=Search and download Health Connect exports from Google Drive.c                 C   s0   d | _ d | _tt d | _| jjdd d S )Nzclawd-health-downloadsT)exist_ok)_service
_availabler   tempfile
gettempdir_download_dirmkdirself r   J/sessions/lucid-sleepy-lamport/mnt/clawd/whatsapp-agent/./gdrive_health.py__init__   s   zGDriveHealthConnector.__init__c              
   C   sr   | j du r/zddlm} | | _ W n ty. } ztd|  d| _ W Y d}~nd}~ww | j dur7| j S dS )zLazy-load Drive service.Nr   )build_drive_servicez"Google Drive service unavailable: F)r   google_authr   	Exceptionloggerwarning)r   r   er   r   r   service   s   
zGDriveHealthConnector.servicec                 C   s<   | j du r| jdu| _ | j rtd | j S td | j S )z'Check if Google Drive API is available.NzGoogle Drive connector: ACTIVEz=Google Drive connector: INACTIVE (falling back to filesystem))r   r   r   infor   r   r   r   	available+   s   


zGDriveHealthConnector.available0   c                 C   s  | j sg S zg d}i }|D ]J}z+d| d}| j j|dddd }|dg D ]}|d	 |vr9|||d	 < q+W q tyX } ztd
| d|  W Y d}~qd}~ww |sctd g W S t	
 t|d }	g }
| D ]8}z+t	|d ddjdd}||	kr|
|d	 |d |d t|ddd W qr ttfy   Y qrw |
jdd dd |
rtdt|
 d|
d d  d |
W S  ty } ztjd| dd g W  Y d}~S d}~ww ) z
        Search Google Drive for Health Connect zip files.

        Returns list of dicts: [{id, name, modifiedTime, size}, ...]
        sorted by modifiedTime descending (newest first).
        )z?name contains 'Health Connect' and mimeType = 'application/zip'z?name contains 'health_connect' and mimeType = 'application/zip'z7name contains 'Health Connect' and name contains '.zip'z7name contains 'health_connect' and name contains '.zip'(z) and trashed = falsez-files(id, name, modifiedTime, size, mimeType)zmodifiedTime desc
   )qfieldsorderBypageSizefilesidzDrive query failed: u    — Nz-No Health Connect files found in Google Drive)hoursmodifiedTimeZz+00:00)tzinfonamesizer   )r#   r(   r%   r)   c                 S   s   | d S )Nr%   r   )xr   r   r   <lambda>t   s    zCGDriveHealthConnector.search_health_connect_files.<locals>.<lambda>T)keyreversezFound z* Health Connect file(s) in Drive (newest: )zDrive search failed: exc_info)r   r   r"   listexecutegetr   r   debugr   utcnowr   valuesfromisoformatreplaceappendint
ValueErrorKeyErrorsortr   lenerror)r   max_age_hoursqueries	all_filesquery
full_queryresultsfr   cutoffrecent_filesmod_timer   r   r   search_health_connect_files6   s|   


z1GDriveHealthConnector.search_health_connect_filesNc              
   C   s  | j sdS zddlm} |s| j j|dd }|d }| j| }| rEt	
  | j d }|dk rEtd|  t|W S | j j|d	}t }|||}	d
}
|
st|	 \}}
|rrtdt| d  d |
r[t|d}||  W d   n1 sw   Y  | jd }td| d|dd t|W S  ty } ztjd| dd W Y d}~dS d}~ww )zn
        Download a file from Google Drive by ID.
        Returns local file path or None on failure.
        Nr   )MediaIoBaseDownloadr(   )fileIdr   i     zUsing cached download: )rL   FzDownload progress: d   %wbi   zDownloaded:  (z.0fz KB)zDrive download failed: Tr/   )r   googleapiclient.httprK   r   r"   r3   r2   r   existsr   now	timestampstatst_mtimer   r   str	get_mediaioBytesIO
next_chunkr4   r:   progressopenwritegetvaluest_sizer   r?   )r   file_idfilenamerK   meta
local_path	age_hoursrequestbuffer
downloaderdonestatusrF   size_kbr   r   r   r   download_file   sN   




z#GDriveHealthConnector.download_file   c                 C   s`   | j |d}|s
dS |d }|d dk r&td|d  d|d  d	 dS | |d
 |d S )z
        Find and download the latest Health Connect file from Drive.

        Returns local file path or None.
        This is the main entry point for the scheduler.
        )r@   Nr   r)   i  zSkipping small file: r(   rQ   z bytes)r#   )rJ   r   r   rm   )r   r@   r"   latestr   r   r   fetch_latest_health_connect   s   z1GDriveHealthConnector.fetch_latest_health_connect   c              
   C   s   z)t   |d  }| j D ]}| j|k r&|  t	d|j
  qW dS  tyD } ztd|  W Y d}~dS d}~ww )z*Remove downloaded files older than N days.iQ zCleaned up old download: zCleanup failed: N)r   rT   rU   r   iterdirrV   rW   unlinkr   r4   r(   r   r   )r   max_age_daysrG   rF   r   r   r   r   cleanup_old_downloads   s   z+GDriveHealthConnector.cleanup_old_downloads)r   )N)rn   )rq   )__name__
__module____qualname____doc__r   propertyr   r   rJ   rm   rp   ru   r   r   r   r   r      s    




L
4r   c                   C   s   t du rt a t S )z(Get the singleton GDriveHealthConnector.N)
_connectorr   r   r   r   r   get_connector   s   r|   )ry   osrZ   r	   loggingr   r   pathlibr   	getLoggerr   r   r{   r|   r   r   r   r   <module>   s    
 D