U
    [Mh'f                     @   s  d dl mZ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Zd dlZd dlmZ d dlZd dlZd dlZd dlmZ d dlmZ d dlZd d	lmZ e ZG d
d deZG dd deZG dd deZ G dd deZ!dGe"e"e"dddZ#e"e"e$dddZ%e"ee" dddZ&e"ee" dddZ'e"ee" dddZ(e"e$dd d!Z)e"ee" dd"d#Z*e"ee" dd$d%Z+e"ee" ee"d&d'd(Z,e-d)ed*d+d,ed*eefee"e"ed-d.d/Z.e-d0ed*d1d,eefe e"ed2d3d4Z/e0d5ed*d1d,eefe"ed6d7d8Z1e0d9ddeeeefe"ee" ee" ej2ed:d;d<Z3e0d=ddeeeefee" ee" ej2ed>d?d@Z4e0dAdBdC Z5e	ej6 e
dDdEdFZ7dS )H    )	APIRouterDependsHTTPExceptionstatusHeader)Session)ListDictOptional)datetimetimezone	timedeltaN)	BaseModel)get_db)get_current_user)urlparsec                   @   s>   e Zd ZU eed< eed< eed< eed< eed< eed< dS )DeveloperActivityapplication_namewindow_titleduration	timestampZbucket_namedeveloper_idN)__name__
__module____qualname__str__annotations__float r   r   ./multi_developer_api.pyr      s   
r   c                   @   s*   e Zd ZU eed< ee ed< eed< dS )ActivityDataPayloadr   
activitiesr   N)r   r   r   r   r   r   r   r   r   r   r   r       s   
r    c                   @   sB   e Zd ZU dZee ed< eed< dZee ed< dZe	ed< dS )DeveloperRegistrationNr   nameemailTactive)
r   r   r   r   r
   r   r   r$   r%   boolr   r   r   r   r"      s   
r"   c                   @   sV   e Zd ZU eed< eed< dZee ed< eed< dZee	 ed< dZ
ee ed< dS )	DeveloperInfor   r#   Nr$   r%   	last_syncr   recent_activities)r   r   r   r   r   r$   r
   r&   r(   r   r)   intr   r   r   r   r'   $   s   
r'    )app_namer   returnc                    s   |    |  }t fdddD r*dS t fdddD rDdS t fddd	D r^d
S t fdddD rxdS t fdddD rdS t fdddD sȈ drt fdddD rdS dS )z5Categorize application based on name and window titlec                 3   s   | ]}| kV  qd S Nr   .0browserZapp_name_lowerr   r   	<genexpr>3   s     z)categorize_application.<locals>.<genexpr>ZchromeZfirefoxZsafariZedgeZoperaZbraver1   c                 3   s   | ]}| kV  qd S r.   r   r0   Zider2   r   r   r3   7   s     )vscodevisual studiopycharmintellijsublimeatomvimemacs	notepad++cursorcodedevelopmentc                 3   s   | ]}| kV  qd S r.   r   )r0   dbr2   r   r   r3   ;   s     ZdatagripZpgadminZmysqlZdbeaverZnavicatZ	sqlserverZoracledatabasec                 3   s   | ]}| kV  qd S r.   r   )r0   Zprodr2   r   r   r3   ?   s     )wordexcel
powerpointoutlookteamsslackdiscordzoomZnotionZobsidianZpostmanproductivityc                 3   s   | ]}| kV  qd S r.   r   r0   Zmediar2   r   r   r3   C   s     )spotifyyoutubevlcmedia playernetflixZtwitchentertainmentc                 3   s   | ]}| kV  qd S r.   r   )r0   systemr2   r   r   r3   G   s     )explorerfinderZterminalcmdZ
powershellztask managerlockdwmwinlogonZcsrssZlsassservicesZsvchost
searchhostnotepad.exec                 3   s   | ]}| kV  qd S r.   r   )r0   Zsys_exer2   r   r   r3   H   s     )rY   rV   rZ   r[   r]   r^   rU   other)loweranyendswith)r,   r   window_title_lowerr   r2   r   categorize_application-   s&    re   )r   r,   r-   c           	         s  dddddddd}|   |   }t fdddD rt| |d< d| kr| dd  }d	| |d
< |d r|d
  d|d  d7  < nd	|  |d
< t| }|d |d< |d |d< nt fdddD rzt| |d< |d rTd|d kr4|d dd\}}d| d| |d
< ||d< nd|d  |d
< |d |d< nd|  |d
< t| |d< d|d< nt fdddD r
t	| |d< |d rd|d  |d
< d|d  |d< n0|
dd
dd}d| d|  |d
< ||d< d |d< nt|| d!ks& dr||d"< |drF|
ddn|}| r| |krt|  dkrd#| d|  |d
< nd#| |d
< ||d< d$|d< nt fd%dd&D rt| |d< |d rd'|d  |d
< |d |d< nd'|  |d
< | |d< d(|d< n~t fd)dd*D rPd+|  |d
< |
dd|d< d,|d< n>t fd-dd.D rd/|  |d
< |
dd|d< d0|d< |d
 s| d1|  |d
< |
dd|d< d2|d< |S )3z;Extract detailed information from window title and app nameN)url	file_pathdatabase_connectionspecific_processdetailed_activityproject_nameproject_typec                 3   s   | ]}| kV  qd S r.   r   r/   r2   r   r   r3   ]   s     z(extract_detailed_info.<locals>.<genexpr>r4   rf    - r   z
Browsing: rj   z ()rk   rl   c                 3   s   | ]}| kV  qd S r.   r   r5   r2   r   r   r3   m   s     )
r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   rg   /   zCoding: z in ZDevelopmentc                 3   s   | ]}| kV  qd S r.   r   )r0   Zdb_toolr2   r   r   r3   ~   s     rC   rh   zDatabase: Connected to zDB: r_   r+   Z64z
Database: ZDatabaserU   ri   zSystem: ZSystemc                 3   s   | ]}| kV  qd S r.   r   )r0   Zofficer2   r   r   r3      s     )rE   rF   rG   rH   zOffice: ZProductivityc                 3   s   | ]}| kV  qd S r.   r   )r0   Zcommr2   r   r   r3      s     )rI   rJ   rK   rL   ZskypezCommunication: ZCommunicationc                 3   s   | ]}| kV  qd S r.   r   rN   r2   r   r   r3      s     )rO   rP   rQ   rR   rS   zMedia: ZEntertainmentz: Work)ra   rb   extract_url_from_browser_titlesplitstripextract_project_from_browserextract_file_pathrsplitextract_project_from_ide_titleextract_database_inforeplacere   rc   lenextract_office_document)	r   r,   inford   
page_titleZproject_infoprojectfilenameZclean_app_namer   r2   r   extract_detailed_infoM   s    



"




r   )r   r-   c           
   
   C   s   dddg}|D ]}t || t j}|rd| ks>d| kr| }|dsXd| }z&t|}|j d|j |j W   S    | Y   S X q|d	 }d	d
ddddddd}|
 }| D ]\}	}|	|kr|    S qqdS )z1Enhanced URL extraction from browser window titlezN^(.+?)\s*-\s*(Google Chrome|Mozilla Firefox|Microsoft Edge|Safari|Opera|Brave)zhttps?://[^\s\)]+zwww\.[^\s\)]+ZhttpZwwwzhttps://z://rp   zhttps://claude.aizhttps://chat.openai.comzhttps://github.comzhttps://stackoverflow.comzhttps://google.comzhttps://youtube.comzhttps://gmail.comzhttps://linkedin.com)ZclaudeZchatgptZgithubZstackoverflowZgooglerP   ZgmailZlinkedinN)research
IGNORECASEgroup
startswithr   ZschemeZnetlocpathrt   ra   items)
r   Zbrowser_patternspatternmatchrf   Zparsedr~   Ztitle_to_urlZ
page_lowerkeyr   r   r   rr      s>    
rr   c                 C   s   ddddddg}|D ]}t || t j}|rt| dkr|d }t| dkrh|d nd	}| d
kr|  S d|krt|ddkr| d|   S |  S q|d   S qdS )z'Extract file path from IDE window titlez&([A-Za-z]:\\[^|<>:*?"]+\.[a-zA-Z0-9]+)z(/[^|<>:*?"]+\.[a-zA-Z0-9]+)zF^([^-]+\.[a-zA-Z0-9]+)\s*-\s*([^-]+)\s*-\s*(Cursor|Code|Visual Studio)zI^([^-]+\.[a-zA-Z0-9]+)\s*-\s*(Cursor|Code|Visual Studio|PyCharm|IntelliJ)z<^([^-]+)\s*-\s*(Cursor|Code|Visual Studio|PyCharm|IntelliJ)$z^([^\\/:*?"<>|]+\.[a-zA-Z0-9]+)   rp   r+   )r?   r@   r7   r8   r9   .ro   N)	r   r   r   r{   groupsr   rt   ra   rs   )r   patternsr   r   Z
first_partZsecond_partr   r   r   rv      s(    	"
rv   c                 C   s*   d}t || t j}|r&|d S dS )z*Extract project name from IDE window titlez:^(.+?)\s*-\s*(Cursor|Code|Visual Studio|PyCharm|IntelliJ)$rp   N)r   r   r   r   rt   )r   Zide_patternr   r   r   r   rx      s
    rx   c                 C   s   d| krz|  dd  }d| krPtd| }|r<|dnd}d| ddS td	| }|rp|dd
dS |ddS dddS )z5Extract project information from browser window titlerm   r   z
localhost:zlocalhost:(\d+)rp   unknownzWeb Development)rk   rl   z([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})zWeb ResearchzWeb BrowsingZBrowser)rs   rt   r   r   r   )r   r~   Z
port_matchZportZ	url_matchr   r   r   ru     s&    ru   c                 C   s4   dddg}|D ] }t || }|r|   S qdS )z Extract database connection infoz
@([^@\s]+)z([a-zA-Z0-9_]+@[a-zA-Z0-9.-]+)z&([a-zA-Z0-9_]+)\s*-\s*([a-zA-Z0-9.-]+)N)r   r   r   )r   Zdb_patternsr   r   r   r   r   ry   &  s    ry   c                 C   sJ   ddddddg}| }|D ]}||kr| |d} q6q| rF| S dS )	z3Extract document name from Office application titlez - Wordz - Excelz - PowerPointz - Microsoft Wordz - Microsoft Excelz - Microsoft PowerPointr+   N)rz   rt   )r   Zoffice_suffixestitlesuffixr   r   r   r|   5  s    r|   )r#   r$   rB   r-   c                 C   s   ddl }ddlm} |   }ddd |D }d| }|rt||   dd }| d| }n|	 j
}| d| }|}	d	}
|tjtjj|k r|	 d|
 }|
d	7 }
q|S )
z2Generate a unique developer ID from name and emailr   N)r   r+   c                 s   s&   | ]}|  s| r|nd V  qdS )r+   N)isalnumisspace)r0   cr   r   r   r3   H  s     z/generate_unique_developer_id.<locals>.<genexpr>_   rp   )hashlibr   ra   rt   joinrs   Zsha256encodeZ	hexdigestnowyearquerymodels	Developerfilterr   first)r#   r$   rB   r   r   Z
clean_nameZ
email_hashZbase_idr   Zoriginal_idZcounterr   r   r   generate_unique_developer_idA  s     

r   z/receive-activity-data.zDeveloper-ID)alias)payloadr   authorizationrB   c                    s  | dstddd|dd }|tjtjj|ktjj|ktjj	dk
 }|sftdddg }| jD ]}zt|jd	d
}t|j|j}	tj|j|j|j|j|t|j|j|	d |	d |	d |	d |	d |	d |	d d}
||
 ||
 W qp tk
r: } ztd|  W Y qpW 5 d}~X Y qpX qpttj|_z.|  ddt| d|j  t||dW S  tk
r } z"|!  tddt"| dW 5 d}~X Y nX dS )z3Receive activity data from remote developer systemszBearer   zInvalid authorization headerZstatus_codeZdetail rp   TzInvalid developer or tokenZ+00:00rf   rg   rh   ri   rj   rk   rl   )r   r   r   r   r   categoryrf   rg   rh   ri   rj   rk   rl   zError processing activity: NsuccesszStored z activities for )r   messageZactivities_countr   i  zDatabase error: )#r   r   rs   r   r   r   r   r   	api_tokenr%   r   r!   r   fromisoformatr   rz   r   r   r   ActivityRecordr   re   addappend	Exceptionprintr   r   utcr(   commitr{   r#   Zrollbackr   )r   r   r   rB   token	developerZstored_activitiesactivityr   Zdetailed_infoZactivity_recorder   r   r   receive_activity_data]  s\    






r   z/register-developerzAdmin-Token)developer_infoadmin_tokenrB   c                    s   ddl }|dd}||kr(tddd|tjtjj| jk }|rXtdd	d| jspt	| j
| j|| _td
}tj| j| j
| j|dd}|| |  || d|j|d|j
 ddS )z%Register a new developer (admin only)r   NADMIN_TOKEN!timesheet-admin-2025-secure-tokenr   Admin access requiredr   i  zDeveloper already registered    T)r   r#   r$   r   r%   r   z
Developer z registered successfully)r   r   r   r   )osgetenvr   r   r   r   r   r   r   r   r#   r$   secretsZtoken_urlsafer   r   Zrefresh)r   r   rB   r   expected_admin_tokenexistingr   r   r   r   r   register_developer  s6    	


r   z/developers)r   rB   c                    s   ddl }|dd}| |kr(tddd|tj }g }|D ]f}|tjtjj	|j	ktjj
ttjtdd	 k }||j	|j|j|j|j||jd
 q@|t|dS )z+List all registered developers (admin only)r   Nr   r   r   r   r      )Zhours)r   r#   r$   r%   r(   r)   r   )
developersZtotal_count)r   r   r   r   r   r   allr   r   r   Z
created_atr   r   r   r   r   countr   r#   r$   r%   r(   r   r{   )r   rB   r   r   r   resultZdevr)   r   r   r   list_developers  s*    

r   z!/developer-summary/{developer_id})r   
start_dateend_datecurrent_userrB   c           
         s  |rt |dd}nt tjjddddd}|rJt |dd}nt tj}|tj	tjj
| k }|stddd|tj	tjj
| ktjj|ktjj|k }|s| |j| | dddi i d	d
S t|}	| |j| | d|	d
S )z-Get activity summary for a specific developerr   r   r   ZhourZminutesecondZmicrosecondi  zDeveloper not foundr   startend)total_activities
total_time
categoriesprojects)r   Zdeveloper_name
date_rangesummary)r   r   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r#   	isoformatprocess_developer_activities)
r   r   r   r   rB   r   r   r   r!   r   r   r   r   get_developer_summary  s8    



r   z/team-dashboard)r   r   r   rB   c              	      s0  | rt | dd}nt tjjddddd}|rJt |dd}nt tj}|tj	tjj
dk }g }d}d}	|D ]v}
|tj	tjj|
jktjj|ktjj|k }t|}||d 7 }|	|d 7 }	||
j|
j|
j|
j|d q| | d	|t|||d
 dd|	ddS )zGet team-wide dashboard datar   r   r   r   Tr   r   )r   r#   r$   r(   r   r     .2fh)r   total_time_formattedr   )r   	team_dataZtotal_developersZteam_totals)r   r   rz   r   r   r   r   r   r   r   r%   r   r   r   r   r   r   r#   r$   r(   r   r{   )r   r   r   rB   r   r   r   r   Ztotal_team_timeZtotal_team_activitiesr   r!   r   r   r   r   get_team_dashboard4  sD    



	r   z/healthc                      s   dt tj ddS )z+Health check endpoint for developer systemsZhealthyzTimesheet server is running)r   r   r   )r   r   r   r   r   r   r   r   r   health_checkn  s    r   )r!   r-   c              	   C   s  | sddi i dddS t dd | D }i }i }d}| D ]}|jpDd}|jpNd}|j}||krlddd||< || d  d	7  < || d
  |7  < ||krdd|jpdd||< || d  d	7  < || d
  |7  < dddddddd}	|	|d}
|||
 7 }q8|dkr|| d nd}| D ]}|d
 d dd|d< q*| D ]}|d
 d dd|d< qRt| ||d dd||d ddt|d	||dS )z*Process activities into summary statisticsr   )r   r   r   r   working_hoursproductivity_percentagec                 s   s   | ]}|j V  qd S r.   )r   )r0   r   r   r   r   r3     s     z/process_developer_activities.<locals>.<genexpr>r`   ZUnknown)r   r   r   rp   r   rq   )r   r   typeg      ?g333333?g      ?g?g        )rA   rD   rM   r1   r`   rU   rT   d   r   r   r   Zduration_formatted)r   r   r   r   Zworking_hours_formattedr   r   r   )	sumr   rk   r   rl   getvaluesr{   round)r!   r   r   r   r   r   r   r   r   Zcategory_weightsZweightr   Zcategory_dataZproject_datar   r   r   r   w  s`    	


r   )r+   )8Zfastapir   r   r   r   r   Zsqlalchemy.ormr   typingr   r	   r
   r   r   r   r   r   Zpydanticr   r   ZschemasZcrudrD   r   Zauthr   r   Zurllib.parser   Zrouterr   r    r"   r'   r   re   dictr   rr   rv   rx   ru   ry   r|   r   Zpostr   r   r   r   ZUserr   r   r   r   r   r   r   r   r   <module>   s   	 j* 
L
0
"59
