U
    i$W                     @   s  d dl mZmZmZmZ d dlmZ d dlmZm	Z	m
Z
 d dlmZmZmZ d dlmZmZmZmZ d dlmZ d dlmZmZ d dlZeeZe Zd	d
dddgZdddddddddddddddddddd d!d"d#d$d%d&d'd(d)gZd*d+ Ze d,ddeefe!ee! ee! ed-d.d/Z"e d0ddeefe!ee! ee! ed-d1d2Z#e d3ddeefee! ee! ed4d5d6Z$e d7ededeefe!ee! ee! ed-d8d9Z%e&d:eefe!ee' e!ed;d<d=Z(dS )>    )	APIRouterDependsHTTPExceptionQuery)Session)functextand_)ListDictOptional)datetime	timedeltatimezonedate)get_db)	DeveloperActivityRecordNZDevelopmentZIDEZCodeZTerminalZDocumentationzVisual Studio CodezIntelliJ IDEAZPyCharmZWebStormzAndroid StudiozSublime TextZAtomZEclipseZNetBeansZVimZEmacszCommand PromptZ
PowerShellzGit BashZChromeZFirefoxZEdgeZSafariZPostmanZInsomniazDocker DesktopzMicrosoft TeamsZSlackZZoomzMicrosoft WordZExcelZ
PowerPointzGoogle Docsc                 C   s>   t | d }t | d d }t | d }| d| d| dS )z1Convert seconds to hours, minutes, seconds format  <   zh zm s)int)ZsecondshoursZminutesZsecs r   ./productivity_api.pyformat_duration   s    r   z0/api/developer/{developer_id}/productivity-hours)developer_id
start_dateend_datedbc              
      sl  z
|rt |dd}nt tjtdd }|rJt |dd}nt tj}|t	tj
| k }|stddd|td| ||ttttd	 }|td
| ||d }|td| ||d }	g }
d}d}|D ]|}|\}}}}}|dkr|| d nd}|
|r.| ndtt|dtt|dt|d||d ||7 }||7 }qdd |D }dd |	D }|dkr|| d nd}|
r|t|
 nd}|j
|jd| | dt|dt|dt|dt|dt|
d|
||dW S  tk
r$    Y nD tk
rf } z$td|  tdt|dW 5 d}~X Y nX dS )z:Calculate productivity hours for a developer from databaseZ+00:00   days  Developer not foundZstatus_codeZdetaila  
            SELECT 
                DATE(timestamp) as work_date,
                SUM(duration) / 3600.0 as total_hours,
                SUM(CASE 
                    WHEN category IN :productive_categories 
                    OR application_name IN :productive_apps 
                    THEN duration 
                    ELSE 0 
                END) / 3600.0 as productive_hours,
                COUNT(DISTINCT application_name) as apps_used,
                COUNT(*) as total_activities
            FROM activity_records
            WHERE developer_id = :dev_id
            AND timestamp >= :start_date
            AND timestamp <= :end_date
            GROUP BY DATE(timestamp)
            ORDER BY work_date DESC
        )dev_idr   r   Zproductive_categoriesZproductive_appsa~  
            SELECT 
                EXTRACT(HOUR FROM timestamp) as hour_of_day,
                SUM(duration) / 3600.0 as total_hours
            FROM activity_records
            WHERE developer_id = :dev_id
            AND timestamp >= :start_date
            AND timestamp <= :end_date
            GROUP BY EXTRACT(HOUR FROM timestamp)
            ORDER BY hour_of_day
        r(   r   r   a  
            SELECT 
                application_name,
                category,
                SUM(duration) / 3600.0 as total_hours,
                COUNT(*) as usage_count
            FROM activity_records
            WHERE developer_id = :dev_id
            AND timestamp >= :start_date
            AND timestamp <= :end_date
            GROUP BY application_name, category
            ORDER BY total_hours DESC
            LIMIT 20
        r   d   N      )r   total_hoursproductive_hoursproductivity_percentage	apps_usedZtotal_activitiesc                 S   s(   g | ] \}}t |tt|d dqS )r+   )hourr   )r   roundfloat).0r1   r   r   r   r   
<listcomp>   s   z4get_developer_productivity_hours.<locals>.<listcomp>c                 S   s>   g | ]6\}}}}||pd t t|d||tkp4|tkdqS )Otherr+   )applicationcategoryr   usage_countZis_productive)r2   r3   PRODUCTIVE_CATEGORIESPRODUCTIVE_APPS)r4   Zapp_namer8   r   countr   r   r   r5      s   
idnamestartend)total_work_hourstotal_productive_hoursr/   Zaverage_daily_hoursZtotal_days_worked)	developer
date_rangeZoverall_statsdaily_productivityhourly_distributionZtop_applicationsz&Error calculating productivity hours:   )r   fromisoformatreplacenowr   utcr   queryr   filterr   firstr   executer   tupler:   r;   fetchallappend	isoformatr2   r3   lenr?   	Exceptionloggererrorstr)r   r   r   r   rA   rB   rE   rG   rH   Z	app_usageZdaily_statsrC   rD   row	work_dater-   r.   r0   
activitiesr/   Zhourly_statsZ	app_statsZoverall_productivityZavg_daily_hourser   r   r    get_developer_productivity_hours!   s    



	
	r_   z//api/developer/{developer_id}/project-breakdownc                    s  z|rt |dd}nt tjtdd }|rJt |dd}nt tj}|t	tj
| k }|stddd|td| ||d	 }|td
| ||d	 }|td| ||d	 }	g }
d}|D ]|}|\}}}}}}}||7 }|
|tt|d||||r$| nd|r4| nd|dkrRtt|| dndd q|
D ].}t|dkr|d | d ndd|d< qbi }|D ]N\}}}|r| nd}||krg ||< || |tt|dd qi }|	D ]J\}}}}}||krg ||< || ||p$dtt|d|d q|D ]}|| dd ||< qB|j
|jd| | dt|dt|
|
r|
d d ndd|
||dW S  tk
r    Y nD tk
r } z$td|  tdt|dW 5 d}~X Y nX dS ) z8Get project-wise breakdown for a developer from databaser    r!      r#   r%   r&   r'   a  
            SELECT 
                COALESCE(project_name, 'Unassigned') as project,
                SUM(duration) / 3600.0 as total_hours,
                COUNT(DISTINCT DATE(timestamp)) as days_worked,
                COUNT(DISTINCT application_name) as apps_used,
                COUNT(*) as activity_count,
                MIN(timestamp) as first_activity,
                MAX(timestamp) as last_activity
            FROM activity_records
            WHERE developer_id = :dev_id
            AND timestamp >= :start_date
            AND timestamp <= :end_date
            GROUP BY project_name
            ORDER BY total_hours DESC
        r)   a  
            SELECT 
                DATE(timestamp) as work_date,
                COALESCE(project_name, 'Unassigned') as project,
                SUM(duration) / 3600.0 as hours
            FROM activity_records
            WHERE developer_id = :dev_id
            AND timestamp >= :start_date
            AND timestamp <= :end_date
            GROUP BY DATE(timestamp), project_name
            ORDER BY work_date DESC, hours DESC
        a  
            SELECT 
                COALESCE(project_name, 'Unassigned') as project,
                application_name,
                category,
                SUM(duration) / 3600.0 as hours,
                COUNT(*) as count
            FROM activity_records
            WHERE developer_id = :dev_id
            AND timestamp >= :start_date
            AND timestamp <= :end_date
            GROUP BY project_name, application_name, category
            ORDER BY project_name, hours DESC
        r   r+   N)project_namer-   Zdays_workedr0   Zactivity_countfirst_activitylast_activityZaverage_hours_per_dayr-   r*   r,   Z
percentageZUnknown)projectr   r6   )r7   r8   r   r9   
   r=   r@   ra   )r-   total_projectsZmost_active_project)rE   rF   Zsummaryprojectsdaily_distributionZproject_applicationsz!Error getting project breakdown: rI   )r   rJ   rK   rL   r   rM   r   rN   r   rO   r   rP   r   rQ   r   rS   rT   r2   r3   rU   r?   rV   rW   rX   rY   rZ   )r   r   r   r   rA   rB   rE   Zproject_statsZdaily_project_hoursZproject_activitiesrg   Ztotal_hours_all_projectsr[   ra   r   r$   Zappsr]   rb   rc   rd   rh   r\   Zdate_strZproject_appsZappr8   r<   r^   r   r   r   get_developer_project_breakdown   s    




 

ri   z(/api/all-developers/productivity-summary)r   r   r   c                    s.  z| rt | dd}nt tjjddddd}|rNt |dd}nt tj}|td||d }g }|D ]}|\}}	}
}}}}|
dkr||
 d nd}d}|r|
dkrt tj|jtjd	 }|	 d
k rd}n|	 dk rd}|
||	tt|
dtt|dt|d|||r0| nd|d	 q|tdd |D }tdd |D }|dkrx|| d nd}tdd |D }| | dt||t|dt|dt|d|rt|t| dndd|dW S  tk
r( } z$td|  tdt|dW 5 d}~X Y nX dS )z+Get productivity summary for all developersr    r!   r   r1   ZminutesecondZmicroseconda]  
            SELECT 
                d.developer_id,
                d.name,
                COALESCE(SUM(ar.duration) / 3600.0, 0) as total_hours,
                COALESCE(SUM(
                    CASE 
                        WHEN ar.category = 'productive' THEN ar.duration * 0.95
                        WHEN ar.category = 'server' THEN ar.duration * 0.90
                        WHEN ar.category = 'browser' THEN ar.duration * 0.20
                        WHEN ar.category = 'non-work' THEN 0
                        ELSE ar.duration * 0.15
                    END
                ) / 3600.0, 0) as productive_hours,
                COUNT(DISTINCT ar.project_name) as projects_worked,
                COUNT(ar.id) as total_activities,
                MAX(ar.timestamp) as last_activity
            FROM developers d
            LEFT JOIN activity_records ar ON d.developer_id = ar.developer_id
                AND ar.timestamp >= :start_date
                AND ar.timestamp <= :end_date
            WHERE d.active = true
            GROUP BY d.developer_id, d.name
            ORDER BY total_hours DESC
        )r   r   r*   Zinactive)Ztzinfor   activeiQ Zidler+   r,   N)	r   r?   r-   r.   r/   Zprojects_countactivities_countrc   statusc                 s   s   | ]}|d  V  qdS )r-   Nr   r4   dr   r   r   	<genexpr>  s     z:get_all_developers_productivity_summary.<locals>.<genexpr>c                 s   s   | ]}|d  V  qdS )r.   Nr   ro   r   r   r   rq     s     c                 s   s   | ]}|d  dkrdV  qdS )rn   rl   r,   Nr   ro   r   r   r   rq     s      r@   )Ztotal_developersactive_developersteam_total_hoursteam_productive_hoursZteam_productivity_percentageZaverage_hours_per_developer)rF   Zteam_summary
developersz3Error getting all developers productivity summary: rI   r'   )r   rJ   rK   rL   r   rM   rQ   r   rS   Ztotal_secondsrT   r2   r3   rU   sumrV   rW   rX   rY   r   rZ   )r   r   r   rA   rB   Zdeveloper_statsru   r[   r(   r?   r-   r.   rg   r]   rc   r/   rn   Z	time_diffrs   rt   Zteam_productivityrr   r^   r   r   r   'get_all_developers_productivity_summaryh  sj    

rw   z$/api/projects-summary/{developer_id}c              
      s`  z|rt |dd}nt tjjddddd}|rNt |dd}nt tj}td}||| ||d }g }d}	|D ]j}
|
d pdd }|
d |
d	 |
d
 |t	||
d r|
d 
dng d}|| d|d kr|	|7 }	q|t|t	|	| | ddW S  tk
rZ } z$td|  tdt|dW 5 d}~X Y nX dS )z+Get activities grouped by project name onlyr    r!   r   rj   au  
            SELECT 
                COALESCE(project_name, 'Uncategorized') as project,
                COUNT(DISTINCT file_path) as files_worked,
                COUNT(*) as total_activities,
                SUM(duration) as total_duration_ms,
                STRING_AGG(DISTINCT category, ', ') as categories
            FROM activity_records
            WHERE developer_id = :dev_id
            AND timestamp >= :start_date
            AND timestamp <= :end_date
            AND project_name IS NOT NULL
            AND project_name != ''
            GROUP BY project_name
            ORDER BY total_duration_ms DESC
        r)      i  r,   r+      z, )ra   Zfiles_countrm   Ztotal_time_secondsZtotal_time_formatted
categoriesznon-workrz   r@   )rg   rf   total_productive_timerF   z Error getting projects summary: rI   r'   N)r   rJ   rK   rL   r   rM   r   rQ   rS   r   splitrT   rV   rU   rW   rX   rY   r   rZ   )r   r   r   r   rA   rB   rN   resultrg   r{   r[   Zduration_secondsZproject_datar^   r   r   r   get_projects_summary  sF    	

r~   z,/api/developer/{developer_id}/update-project)r   activity_idsra   r   c              
      s   zt| ttj| k }|s,tddd| tttj| ktj	|j
d|idd}|  d|||dW S  tk
r } z,|  td	|  td
t|dW 5 d}~X Y nX dS )z+Update project name for specific activitiesr%   r&   r'   ra   F)Zsynchronize_sessionT)successZupdated_countra   r   zError updating project: rI   N)rN   r   rO   r   rP   r   r   r	   r>   Zin_updateZcommitrW   ZrollbackrX   rY   rZ   )r   r   ra   r   rE   updatedr^   r   r   r   update_activity_project  s2    



r   ))Zfastapir   r   r   r   Zsqlalchemy.ormr   Z
sqlalchemyr   r   r	   typingr
   r   r   r   r   r   r   Zdatabaser   Zmodelsr   r   ZloggingZ	getLogger__name__rX   Zrouterr:   r;   r   getrZ   r_   ri   rw   r~   Zpostr   r   r   r   r   r   <module>   s   
                      
   'fJ