U
    [MhH                     @   sn   d Z ddlmZmZmZ ddlmZmZmZ ddlm	Z	 ddl
mZmZ ddlZddlmZ G dd	 d	ZdS )
zF
Realistic Hours Calculator - More accurate working hours calculation
    )datetime	timedeltatimezone)DictListOptional)Session)funcand_N)ActivityWatchClientc                   @   s   e Zd Zdd ZeedddZeedddZe	e
j edd	d
Zeeef edddZeeef edddZeee	e dddZeeeee	e dddZe	e edddZeeeeedddZdS )RealisticHoursCalculatorc                 C   s   dddd| _ d S )Ng      @g       @)lowmediumhigh
thresholds)self r   ./realistic_hours_calculator.py__init__   s    z!RealisticHoursCalculator.__init__)hoursreturnc                 C   s`   |dkrdS t |d }|d }|d }|dkr:| dS |dkrL| dS | d| dS dS )z@Convert decimal hours to readable format (e.g., 5.5 -> '5h 30m')r   0h<   mhzh N)int)r   r   Ztotal_minutesZ
hours_partZminutes_partr   r   r   format_time_readable   s    

z-RealisticHoursCalculator.format_time_readablec                 C   sP   || j d k rddddddS || j d k r<ddd	d
ddS ddddddS dS )z3Get status color and message based on working hoursr   z#ef4444z#fef2f2zBelow targetu   🔴)statuscolor
backgroundmessageiconr   z#f59e0bz#fffbebzOn tracku   🟡r   z#22c55ez#f0fdf4z
Excellent!u   🟢Nr   )r   r   r   r   r   get_status_info%   s(    	z(RealisticHoursCalculator.get_status_info)
activitiesr   c                 C   s4  |sddi dS i }d}|D ]}|j }|j}||7 }||krLddi d||< || d  |7  < || d  d7  < |j}||| d krd|| d |< || d |  |7  < qd}i }	| D ]X\}}
|
d }|d	 }|d
kr|}||7 }||ddd|	|< q|dkr2|}||7 }||ddd|	|< q|dkr\|}||7 }||ddd|	|< q|dkr| |
d }||d  }|||d  7 }|||| dd|	|< q|dkr| |
d }||d  }|||d  7 }|||| dd|	|< q|d }||d 7 }||ddd|	|< q|d	 |d	 |	dS )z<Calculate realistic working hours based on activity patterns        )working_hourstotal_hours	breakdownr   )
total_timecountappsr)   r*      r+   i  Zdevelopmentd   zAll coding/development work)r'   r&   Z
percentagereasonZdatabasezAll database workZproductivityzAll productivity toolsZbrowserz!% estimated work-related browsingotherz#% estimated work-related activitiesg?
   zMinimal work-related time)categorydurationapplication_nameitemsanalyze_browser_usageanalyze_other_usage)r   r$   Zcategory_datar)   activityr1   r2   Zapp_nameZworking_timer(   dataZcat_timeZ	cat_hoursr&   Zwork_percentager   r   r   !calculate_realistic_working_hours@   s    





	z:RealisticHoursCalculator.calculate_realistic_working_hours)r+   r   c                 C   s   dS )z2Analyze browser usage to determine work percentageU   r   )r   r+   r   r   r   r5      s    z.RealisticHoursCalculator.analyze_browser_usagec                 C   s   ddddg}t | }d}| D ]n\}}d| ksDd| krR||d 7 }q$d	| krl||d
 7 }q$d| kr||d
 7 }q$||d 7 }q$|dkrt|| d S dS )z:Analyze 'other' category apps to determine work percentagezdatagrip64.exezPostman.exezSnippingTool.exezLockApp.exer   ZdatagripZpostmang      ?Zsnippingg?Zlockappg      ?r-   2   )sumvaluesr4   lowerr   )r   r+   Zwork_related_appsr)   Z	work_timeZapptimer   r   r   r6      s$    z,RealisticHoursCalculator.analyze_other_usage)
start_dateend_dater   c                 C   s  t  }|jddddd}|jddddd}z|||}W n8 tk
rr } ztd|  g  W Y S d}~X Y nX i }|D ].}|d  }||krg ||< || | q|g }	| }
| }|
|kr|
|kr||
 }g }|D ]6}td	d
|d |d |d |d d }|| q| |}|d }|d }| 	|}|	|

dt|dt|d| || |t|dkr|| d nddt||d |d |d |d |d |d d nB| 	d}|	|

ddddddd|d |d |d ddi d |
tdd 7 }
q|	S )!z6Calculate daily hours directly from ActivityWatch datar   ZhourZminutesecondZmicrosecond   ;   ?B z#Error fetching ActivityWatch data: N	timestampZMockActivityr   r1   r2   r3   )r1   r2   r3   rG   r&   r'   %Y-%m-%d   r-   r,   r   r   r    r!   r"   r(   dater&   r'   Zworking_hours_formattedZtotal_hours_formattedZproductivity_percentageZactivities_countr   Zstatus_colorZstatus_backgroundZstatus_messageZstatus_iconr(   r%   r   No activity   ⚪Zdays)r   replaceZget_activity_data	ExceptionprintrK   appendtyper9   r#   strftimeroundr   lenr   )r   r@   rA   Z	aw_clientZactivity_dataedaily_activitiesr7   activity_dateresultcurrent_dateend_date_onlyday_activitiesZmock_activitiesZmock_activity
hours_datar&   r'   status_infor   r   r   (calculate_daily_hours_from_activitywatch   s    






zARealisticHoursCalculator.calculate_daily_hours_from_activitywatch)dbuser_idr@   rA   r   c                 C   s  |j ddddd}|j ddddd}|tjttjj|ktjj|ktjj|ktjj	 
 }i }|D ],}|j }||krg ||< || | qpg }	| }
| }|
|kr|
|krp||
 }| |}|d }|d }| |}|	|
dt|d	t|d	| || |t|dkr6|| d
 nddt||d |d |d |d |d |d d nB| d}|	|
ddddddd|d |d |d ddi d |
tdd7 }
q|	S )z.Calculate realistic working hours for each dayr   rB   rD   rE   rF   r&   r'   rH   rI   r-   r,   r   r   r    r!   r"   r(   rJ   r%   r   rL   rM   rN   )rO   ZquerymodelsActivityRecordfilterr
   rb   rG   Zorder_byZascallrK   rR   r9   r#   rT   rU   r   rV   r   )r   ra   rb   r@   rA   r$   rX   r7   rY   rZ   r[   r\   r]   r^   r&   r'   r_   r   r   r   calculate_daily_hours1  sx    



	






z.RealisticHoursCalculator.calculate_daily_hours)
daily_datar   c              
   C   s   |sdddddddddS t dd |D }tdd |D }td	d |D }td
d |D }tdd |D }|rt|dd dnd}t|||rt|t| dndt|d||||r|d |d dnddS )z!Calculate summary from daily datar   r%   N)Z
total_daysworking_daysZavg_working_hourstotal_working_hoursdays_above_targetdays_on_trackdays_below_targetbest_dayc                 s   s   | ]}|d  V  qdS )r&   Nr   .0Zdayr   r   r   	<genexpr>  s     z7RealisticHoursCalculator.get_summary.<locals>.<genexpr>c                 S   s   g | ]}|d  dkr|qS )r&   r   r   ro   r   r   r   
<listcomp>  s      z8RealisticHoursCalculator.get_summary.<locals>.<listcomp>c                 S   s   g | ]}|d  dkr|qS )r   r   r   ro   r   r   r   rr     s      c                 S   s   g | ]}|d  dkr|qS )r   r   r   ro   r   r   r   rr     s      c                 S   s   g | ]}|d  dkr|qS )r   r   r   ro   r   r   r   rr     s      c                 S   s   | d S )Nr&   r   )xr   r   r   <lambda>      z6RealisticHoursCalculator.get_summary.<locals>.<lambda>)keyrI   rK   r&   )rK   r   )r<   rV   maxrU   )r   rh   rj   ri   rk   rl   rm   rn   r   r   r   get_summary  s<    z$RealisticHoursCalculator.get_summaryc                 C   s8   |  ||}| |}||| j|d|dddS )zFGenerate complete realistic daily hours report from ActivityWatch datarH   )startend)rh   summaryr   Z
date_range)r`   rx   r   rT   )r   ra   rb   r@   rA   rh   r{   r   r   r   calculate_daily_report  s    
z/RealisticHoursCalculator.calculate_daily_reportN)__name__
__module____qualname__r   floatstrr   r   r#   r   rc   rd   r9   r   r5   r6   r   r`   r   rg   rx   r|   r   r   r   r   r      s$   u	Y  N%  r   )__doc__r   r   r   typingr   r   r   Zsqlalchemy.ormr   Z
sqlalchemyr	   r
   rc   Zmy_activitywatch_clientr   r   r   r   r   r   <module>   s   