U
    i1                 
   @   s  d dl mZmZmZmZmZ ed zd dlmZmZm	Z	m
Z
mZmZmZmZmZ e  e Ze	 Ze
 Ze Ze Ze Ze Ze Zededd  ededd	  ed
edd	  W nr ek
r Z zede  ed W 5 dZ[X Y n: ek
r> Z zede  ed W 5 dZ[X Y nX d dlmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z& d dl'm(Z( d dl)m*Z* d dl+m,Z, d dl-m.Z.m/Z/ d dl0m1Z1 d dl2m3Z3m4Z4m5Z5m6Z6 d dl7m8Z8 d dl9Z9d dl:Z:d dl;m;Z;m<Z< d dl=Z=d dl>Z>d dl?Z?e?j@e?jAdd e?BeCZDd dlEZEd dlFmGZG d dlHmIZI d dlJmKZK d dlLZLd dlMmNZN d dlHZHd dlOZOdd  ZPd!d" ZQeeCZRe(eR ze9jSd#se9jSd$re9jSd$ e9jSd#< d%e9jSkrd&e9jSd%< d'e9jSkrd&e9jSd'< d(e9jSkrd)e9jSd(< d*e9jSkrd+e9jSd*< W n4 ek
rN ZT zeDUd,eT  W 5 dZT[TX Y nX d-d. ZVe9jSd/ZWeWrteWd0kreV ZWed1eWdd2  d3 eWe9jSd/< eWeRjXd/< e<d4d5eRjXd6< e9jSd7ZYeYreYd0kreV ZYed8eYdd2  d3 eYe9jSd7< eYeRjXd7< e<d9d5eRjXd:< dtd<d=ZZd>d? Z[d@dA Z\eR]dBdCdD Z^eR]dEeQdFdG Z_eR]dHdIdJ Z`eR]dKdLdM ZaeR]dNdOdP ZbeR]dQdRdS ZceR]dTeQdUdV ZdeR]dWeQdXdY ZeeR]dZeQd[d\ ZfeR]d]eQd^d_ ZgeR]d`dadb ZheR]dcddde ZieR]dfdgdh ZjeR]dieQdjdk ZkeR]dldmdn Zlz
e[  W n4 ek
r Z zeDUdoe  W 5 dZ[X Y nX eR]dpdqdr ZmeR]dsdtdu ZneR]dvdwdx ZoeR]dyeQdzd{ Zpd dlHmIZI d|eq eq d}d}g d eI d~ZreRj]ddgddd ZseR]ddd ZteR]ddd ZueR]ddd ZveR]ddd ZweR]ddd ZxeR]ddd ZyeRj]ddgddd Zze8 Z{eRj]ddgddd Z|eR]ddd Z}eR]ddd Z~eR]ddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgdddÄ ZeR]dġddƄ ZeR]dǡddɄ ZeR]dʡdd̄ ZeRj]ddgdddτ ZeRj]ddgddd҄ ZeRj]ddgdddՄ ZeRj]ddgddd؄ ZeRj]ddgdddۄ ZeRj]ddgdddބ ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgdd d ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgdd	d
 ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgddd ZeRj]ddgdd d! ZeRj]d"dgdd#d$ ZeRj]d%dgdd&d' ZeRj]d(dgdd)d* ZeRj]d+dgdd,d- ZeRj]d.dgdd/d0 ZeRj]d1dgdd2d3 ZeRj]d4dgdd5d6 ZeRj]d7dgdd8d9 ZeRj]d:dgdd;d< ZeRj]d=dgdd>d? ZeRj]d@dgddAdB ZeRj]dCdDgddEdF ZeRj]dGdgddHdI ZeRj]dJdgddKdL ZeRj]dMdgddNdO ZeRj]dPdgddQdR ZeR]dSdTdU ZeR]dVdWdX ZeR]dYdZd[ ZeRj]d\dgdd]d^ ZeRd_d`da ZeRdbdcdd ZeR]dedfdg ZeRdhdidj ZeRdkdldm ZeRjĐdndo ZeCdpkreRjƐdqdrds dS (u      )init_error_loggercapture_exceptioncapture_messageset_tagset_contextzai-test-case-generator-main)	apply_to_process_envget_current_configget_website_configget_database_configget_ai_configget_integrations_configget_email_configget_security_configget_logging_configu*   ✅ Loaded configuration for environment: nameUnknownz   Website URL: urlN/Az   Database: Z
mongodb_dbu0   ⚠️ Centralized configuration not available: z6   Falling back to environment variables and .env fileNu0   ⚠️ Error loading centralized configuration: )	Flaskrequestjsonify	send_filerender_templateafter_this_requestredirecturl_forsession)CORS)fetch_issueAzureClient)generate_test_caseget_openai_api_keygenerate_test_case_from_image)save_test_scriptsave_excel_reportextract_test_type_sectionsparse_traditional_format)MongoHandlerdatetime	timedeltaz4%(asctime)s - %(name)s - %(levelname)s - %(message)s)levelformat)urlparse)Lockwraps)ObjectIdc                    s   t   fdd}|S )z.Decorator to require authentication for routesc            	   
      s   t jd}|r|ds.t j}td| S |dd }z^t }||}|r|dr|d }t	|d |d	 |d
 |dddt _
 | |W S W n6 tk
r } ztdt	|  W 5 d }~X Y nX t j}td| S )NAuthorizationBearer z/signin?redirect=    successuseridemailr   roler:   r;   r   r<   zError in auth decorator: )r   headersget
startswithr   r   splitr)   verify_jwt_tokenstrcurrent_user	Exceptionloggererror)	argskwargsauth_headerZcurrent_urltokenmongo_handlerverifieduef 0/var/www/html/testcasegenerator.evdpl.com/app.pydecorated_function@   s(    


&z(require_auth.<locals>.decorated_functionr1   rQ   rT   rR   rP   rS   require_auth>   s    rV   c                    s   t   fdd}|S )z?Decorator to require authentication for web routes (HTML pages)c                     s
    | |S NrR   )rH   rI   rP   rR   rS   rT   c   s    z,require_web_auth.<locals>.decorated_functionr1   rU   rR   rP   rS   require_web_autha   s    	rX   ZLANGCHAIN_API_KEYZLANGSMITH_API_KEYZLANGCHAIN_TRACING_V2trueZLANGCHAIN_TRACKING_V2LANGCHAIN_PROJECTopenai-cost-trackingZLANGSMITH_ENDPOINTzhttps://api.smith.langchain.comz$LangSmith env normalization failed: c                     s>   ddl ddl} | j| j d  d fddtdD S )z Generate a secure JWT secret keyr   Nz-_ c                 3   s   | ]}  V  qd S rW   )choice).0_ZalphabetsecretsrR   rS   	<genexpr>   s     z&generate_jwt_secret.<locals>.<genexpr>@   )ra   stringascii_lettersdigitsjoinrange)rd   rR   r`   rS   generate_jwt_secret   s    ri   JWT_SECRET_KEY$your-secret-key-change-in-productionzGenerated new JWT secret:    ...   daysZJWT_ACCESS_TOKEN_EXPIRESZ
SECRET_KEYzGenerated new session secret:    ZPERMANENT_SESSION_LIFETIME   c                 C   s  zt   }|d d }| D ]l}z*tjtjt |}tj|sPW qtj|ddD ]\}}}|D ]}	zrtj||	}
tj|
}|| |krzt	|
 W n8 t
k
r } ztd|
 d|  W 5 d }~X Y nX W ql t
k
r   Y qlY qlX ql|D ]F}tj||}zt|s,t| W n t
k
rD   Y nX qq^W q t
k
r } ztd| d|  W 5 d }~X Y qX qW n4 t
k
r } ztd|  W 5 d }~X Y nX d S )N<   F)topdownzSkip removing file : z+Filesystem cleanup encountered an error in zFilesystem cleanup failed: )timeospathabspathrg   getcwdexistswalkgetmtimeremoverE   rF   debuglistdirrmdirwarning)Ztarget_directoriesmax_age_hoursnowcutoffZrel_dirbase_dirrootdirsfilesr   fpmtime_edZdprO   rR   rR   rS   _cleanup_old_files   s>    
,.r   c               
   C   sd   dd } z$t j| dd}|  td W n2 tk
r^ } ztd|  W 5 d}~X Y nX dS )zBRun initial cleanup shortly after startup and then every 24 hours.c                  S   sD   t jdddg} td t| dd td t| dd q(d S )Ntests	generateduploads
   rr   )r   iQ )rw   rx   rg   rv   sleepr   )Ztarget_dirsrR   rR   rS   _runner   s    

z:_start_filesystem_cleanup_background_task.<locals>._runnerT)targetdaemonz8Filesystem cleanup background task started (24h policy).z)Failed to start filesystem cleanup task: N)	threadingThreadstartrF   inforE   r   )r   trO   rR   rR   rS   )_start_filesystem_cleanup_background_task   s    r   c                   C   s   t dS )z&Render the shared navigation componentzshared/navigation.htmlr   rR   rR   rR   rS   render_navigation   s    r   /c                  C   s   t  d} td| dS )N%Y%m%d%H%M%Sz
index.html	timestamp)r+   r   strftimer   r   rR   rR   rS   index   s    r   z
/analyticsc                   C   s   t dS )zAnalytics dashboard pagezanalytics.htmlr   rR   rR   rR   rS   analytics_dashboard   s    r   z/documentationc                   C   s   t dS )zDocumentation pagezdocumentation.htmlr   rR   rR   rR   rS   documentation   s    r   z/comparisonc                   C   s   t dS )z$Competitive analysis comparison pagezcomparison.htmlr   rR   rR   rR   rS   
comparison   s    r   z/signinc                  C   sJ   z(t jd} t jd}td| |dW S  tk
rD   td Y S X dS )zDSign in page with optional desktop redirect if already authenticatedr   
return_urlzsignin.html)r   r   N)r   rH   r?   r   rE   )Zredirect_paramr   rR   rR   rS   signin   s    r   z/signupc                   C   s   t dS )zSign up pagezsignup.htmlr   rR   rR   rR   rS   signup  s    r   z
/dashboardc                   C   s   t dS )zUser dashboard pagezdashboard.htmlr   rR   rR   rR   rS   	dashboard  s    r   z/automationc                   C   s   t dS )zAutomation scripts pagezautomation.htmlr   rR   rR   rR   rS   
automation  s    r   z/execution-historyc                   C   s   t dS )zExecution history pagezexecution-history.htmlr   rR   rR   rR   rS   execution_history  s    r   z/execution-reportc               
   C   s  t jd} t jd}|r| sz*t }||}|rH|drH|d } W n< tk
r } ztd| dt|  W 5 d}~X Y nX | st	dddd	fS t }|
| }|s|| d}|r| |d
|ddd|ddgid}n| t dddgid}| g}zt|dr*|jd| ind}d}|rB|d}|sz:|jd| iddi}	|	D ]}
|t|
d qdW n tk
r   Y nX n
|| W n tk
r   Y nX tt|}|j|dd}t	d||| dS )zExecution report page
testCaseIdexecutionIdz*Error getting test case ID from execution ru   N
error.htmlz(Test Case ID or Execution ID is requirederror_message  
created_atsource_typeZgenerated_scripttest_case_typesZ
Functional)_idr   r   	test_datagenerated_scripts_collectionr   test_case_idr7   i  r   limitzexecution-report.html)	test_case
executionsr   )r   rH   r?   r)   get_execution_by_idrE   rF   rG   rC   r   get_test_case_by_idget_script_contentr+   utcnowhasattrr   find_onefindappendlistdictfromkeysget_execution_history)r   execution_idmongo	executionrO   r   Z
script_docZids_to_queryZ	mapped_idZcursordocr   rR   rR   rS   execution_report  sl    
,

  
 
r   z/download-desktop-appc               
      s  z~ddl } ddlm}m}m} |jdp.d tfdddD }|rbt	d	d
ddfW S | j
dd| j
dd| j
ddg}g }zddksdksdkrdkrdkrddg}n.dksdksdkrddg}nddddg}W n" tk
r   ddddg}Y nX g }|D ]}zh| j
|r| |D ]J}	|	  t fdd|D r<| j
||	}
||
| j
|
f q<W n tk
r   Y nX q|s,|D ]z}z\| j
|r| |D ]>}	|	   dr| j
||	}
||
| j
|
f qW n tk
r&   Y nX q|sJtd| |d d!d" |jd#d$ d%d& |d d }||d%| j
|d'd(W S  tk
r } z td)|  |d*d+d" W 5 d}~X Y nX dS ),z&Download desktop application installerr   N)r   abortr   
User-Agentr\   c                 3   s   | ]}| kV  qd S rW   rR   )r^   keyword)
user_agentrR   rS   rb   z  s     z'download_desktop_app.<locals>.<genexpr>)linuxZubuntuZdebianZfedoraZcentosZredhatZsuseZarchZlinux_not_supportedzSorry, we currently only have Windows and Mac versions available. You can try using the web version with the same functionality, or use Windows/Mac to download the desktop app.)rG   message   desktop-appz
dist-freshzdist-newdistzmac os x	macintoshZmacZiphoneZipad.dmg.pkgZwindowsZwin64win32.exe.msic                 3   s   | ]}  |V  qd S rW   )endswith)r^   ext)
lower_namerR   rS   rb     s     )r   r   r   r   z;Desktop app installer not found in expected directories: %s  z'Desktop application installer not found)descriptionc                 S   s   | d S )Nr7   rR   xrR   rR   rS   <lambda>      z&download_desktop_app.<locals>.<lambda>Tkeyreversezapplication/octet-stream)as_attachmentdownload_namemimetypez)Error downloading desktop app installer:   z/Error downloading desktop application installer)rw   flaskr   r   r   r>   r?   loweranyr   rx   rg   rE   isdirr   r   r}   r   rF   rG   sortbasename)rw   r   r   r   Zis_linuxZcandidate_dirsZpreferred_extsZcandidate_filesr   r   	full_pathZinstaller_pathrO   rR   )r   r   rS   download_desktop_appo  sz    (




r   z/reset-passwordc                   C   s   t dS )zReset password pagereset-password.htmlr   rR   rR   rR   rS   reset_password  s    r   z/reset-password-confirmc                  C   sR   t jd} | stdddS t }|| }|d s@tdddS td| |d d	S )
z Password reset confirmation pagerK   r   zInvalid or missing reset tokenrG   r8   zInvalid or expired reset tokenzreset-password-confirm.htmlr;   )rK   r;   )r   rH   r?   r   r)   Zverify_password_reset_token)rK   rL   token_resultrR   rR   rS   reset_password_confirm  s    
r   z/admin-dashboardc                   C   s   t dS )zAdmin dashboard pagezadmin-dashboard.htmlr   rR   rR   rR   rS   admin_dashboard  s    r   z/testc                   C   s"   t d tdt ddS )Nz=== TEST ENDPOINT CALLED ===zServer is working!r   )r   r   )rF   r   r   r+   r   r   rR   rR   rR   rS   test  s    
r   z(Failed to init filesystem cleanup task: z/selenium-statusc               
   C   s|   z*ddl m}  |  }|t|d}t|W S  tk
rv } z.td|  tdt|ddf W Y S d}~X Y nX dS )	z8Check if Selenium WebDriver can initialize on this host.r   )check_selenium_availability)selenium_availableZwill_be_used_in_url_flowzSelenium status check failed: F)r   rG   r   N)ai.url_generatorr   boolr   rE   rF   rG   rC   )r   Z	availablestatusrO   rR   rR   rS   selenium_status  s    
r  z/test-emailc               
   C   s   zVddl m}  |  }|r4tddt ddW S tddt ddd	fW S W nb tk
r } zDtd
t	|  tddt	| t ddd	f W Y S d}~X Y nX dS )zTest email notification systemr   )test_email_configurationr8   zTest email sent successfully!r   r  r   r   rG   z5Failed to send test email. Check email configuration.r   z#Error testing email configuration: zError testing email: N)
utils.email_notifierr  r   r+   r   r   rE   rF   rG   rC   )r  r8   rO   rR   rR   rS   
test_email  s2    

r  /test-error-notificationc               
   C   s   zxddl m}  td}| ddddt  d|d	}|rVtd
dt ddW S tddt dddfW S W nb tk
r } zDt	dt
|  tddt
| t dddf W Y S d}~X Y nX dS )z'Test critical error notification systemr   ) send_critical_error_notificationz;This is a test critical error for email notification systemZ
TEST_ERRORz Test critical error notificationTr  )r   endpointr   )Z
error_typer   context	exceptionr8   z*Test error notification sent successfully!r   r  rG   zBFailed to send test error notification. Check email configuration.r   z"Error testing error notification: zError testing notification: N)r  r	  rE   r+   r   	isoformatr   r   rF   rG   rC   )r	  Z
test_errorr8   rO   rR   rR   rS   test_error_notification  sD    


r  z/resultsc                  C   s   t jdpt jd} td|   | rt }|| }td|  |r|jd| i}|rp|di ni }t	d||dS t
d	|   t	d
dddfS t	d
dddfS )Nr   rK   z!Received request with key/token: z#Retrieved URL params from MongoDB: r   status_timestampszresults.html)
url_paramsr  zNo data found for key/token: r   z[The requested test case data could not be found. The link may have expired or been invalid.r   r   z/Invalid URL. Please use a valid test case link.r   )r   rH   r?   rF   r   r)   Zget_url_data
collectionr   r   r   )	short_keyrL   r  documentr  rR   rR   rS   resultsC  s    
r  Fr\   )is_generatingcompleted_typestotal_typesphasecurrent_test_typelogprogress_percentagelockz/api/generatePOST)methodsc            J         s  z>t d d } tjrxztj} t d W q tk
rt } z*t d|  tddidf W Y W S d }~X Y qX ntj} t d t dt	|   t d	| rt
|  nd
  tjr2t dt
tj   tj D ]H\}}t d| d|j dt|drt| nd  |d qg tjrT| d| dg n6t| drl| dn| dg ttrgttrgstddidfW S d }tjd}|rL|drLz<|dd }t }||}|r|dr|d }W n8 tk
rJ } zt dt|  W 5 d }~X Y nX | sdtddidfW S | d}	|	stddidfW S t }
d }zt }d |	| r| d!rt| d!g nd|
 d"| d#tjd$tj |	| r
| d!r
t| d!g ndd%}|r4|d&|d'< |d(|d)< |!| W n8 tk
rx } zt d*t|  W 5 d }~X Y nX t"d+  d,t"d-< t# t"d.< d/t"d0< d1t"d2< g t"d3< dt"d4< d1t"d5< |	d6krt#d7d8 D t"d9< nZ|	d:krt#d;d8 D t"d9< n8| d!g }t|tr |g}t#fd<d8|D t"d9< W 5 Q R X |	d:kr$t d= t d>|   t$d?|   g }| d@i }|d:d1% }t dA|  t$dB|  |st$dC tddDidfW S ztt$dE|  t&|}t'|j(|j)gst$dF tddGidfW W S t$dH|  zdt*j|dId$dJidK}t$dL|j+  |j+dMk sh|j+dNkrt$dO|j+  t dP|j+ dQ W nD tk
r } z$t$dR|  t dS| dQ W 5 d }~X Y nX t$dT z"ddUl,m-} t dV t$dW W n` tk
r^ } z@t dX|  t$dY|  tddX| idZf W Y W W S d }~X Y nX rjnd[g}t d\  t d]|  t$d^|  dd l.}t|/ }t$d_|  dd l0}t$d` ddadb}t"d+ ( dct"d0< t"d3 1dd| de|  W 5 Q R X |j2|||||r,|d&nd fd,df3  tdg|iW W S  t*j4k
r } z@t"d+  dht"d-< W 5 Q R X tddit| idf W Y W S d }~X Y nt tk
r } zTt djt|  t"d+  dht"d-< W 5 Q R X tddjt| idZf W Y W S d }~X Y nX n|	d6krZt dk t dt
tj   t dlt
tj   g }dmtjkrt dn tddoidfW S tjdm }t dp|j dt|drt| nd  |d |jd1k	rt dq tddridfW S dd l.}t5 6ds dtt|/ d du  }t7j89t7j8:t;dvdw}t7j<|d,dx t7j8=|jd }dy| | }t7j89||}|>| zddzl?m@} 	st7A| t"d+  dht"d-< W 5 Q R X tddidfW W S d } d,}!g }"D ]}#zt d{|# d| |||#gd}}$|$
rj| 
r4| d~|$ 7 } n|$} t"d+ " | dt|# }%t"d. B|% W 5 Q R X n(|"1d|# d| t d|# d| dh}!W 	q tCk
rZ } zt|}&|"1|& t jd|# d|& d,d dh}!d|&D k
sd|&D krJt7j8E|rt7A| t"d+  dht"d-< W 5 Q R X tFd|&ddf W Y   W W S W 5 d }~X Y n` tk
r } z@|"1d|# dt|  t jd|# dt| d,d dh}!W 5 d }~X Y nX 	q| szt7A| t"d+  dht"d-< W 5 Q R X d}&|"rf|&d|"d  7 }&|"D ]Z}'d|'ks"d|'kr.d}& qfn4d|'D ksJd|'D kr
tFddddf  W W S q
td|&idfW W S d| }(tG| |(})tH| |(}*|)r|*r|)|*d}+g },tI| d~D ]4\}-}.|.% rd|-d  }/|,1|/|.d1d qtJ| }0g }1|0r4|0 D ] \}2}3tK|3|2d}4|1L|4 qntK| }1z:tjdprtjdprtjMdprtjMd}5W n tk
r   d }5Y nX |5rzdd l7}6|6j8N|5}5W n tk
r   Y nX t }|O|,d6||1|5d|d6|r|d& nd }t }7|7|
 P }8z||rd|d6dt|+|8|
 |7 |8d	| d#tjd$tj d6dd%}|r~|d&|d'< |d(|d)< |!| W n8 tk
r } zt dt|  W 5 d }~X Y nX t"d+  t"d9 Q t"d.< dht"d-< W 5 Q R X td,||+dW W S t7A| t"d+  dht"d-< W 5 Q R X tddidfW W S W q> tk
rT } zt7j8E|rnt7A| t"d+  dht"d-< W 5 Q R X t jdt| d,d dt| d}&dt|D ksdt|D krd}&nRdt|D ks dt|D krd}&n(dt|D ks*dt|D kr.d}&td|&idZf W Y W S d }~X Y nX 
ntj} | dd}	| d!g }t d|	  t d|  | d| dg ttrgstddidfW S t|tr|g}t d| dt| d t d  t|dIkr:t dt| d n<t|dkr`t dt| d nt dt| d i }+i }9d,}!|D ] t d   d } |	dkr| d}:t d   z2tR |:};|;st d   d|9 < W qW nZ tk
rP } z:t d  dt|  dt| |9 < W Y qW 5 d }~X Y nX t d  d|;dd  |;di }<|<d}=|<dd  }> fdd}?|?|=}@D ]L}#zt d{|# d   tS|@p|>|>|#gd}$|$r| r| d~|$ 7 } n|$} t"d+ n   dt|# }%t"d. B|% tt"d. tt"d9  d }At dtt"d.  dtt"d9  d|AdśdƝ W 5 Q R X t d|# d   nt d|# dɈ   dh}!W nH tk
r } z(t d|# d  dt|  dh}!W 5 d }~X Y nX qn|	dkrt dˡ | d̡}Bt d|B  t dt	|B  |Brt dt|BtTrjt
|B ndЛ  t dt|BtTrt
|BU ndЛ  |Brt'|BU rt d|B  tV|BdӍ}Cn<t dԡ t dtW|B d|Brt'|BU ndh  tV }CzV|CX g}D|Dr*t|Ddkr\t|Cd׃rN|CjYrN|CjY}E|E|9 < nd|9 < W qW nZ tk
r } z:t dو  dt|  dt| |9 < W Y qW 5 d }~X Y nX |Dd }FD ]}#ztS|Fd |Fd |#gd}$|$r| r | d~|$ 7 } n|$} t"d+ n   dt|# }%t"d. B|% tt"d. tt"d9  d }At dtt"d.  dtt"d9  d|AdśdƝ W 5 Q R X t d|# d   ndh}!W nB tk
r } z"t d|# dt|  dh}!W 5 d }~X Y nX q| st d܈  dݝ qt dވ  dߝ d19dd8  D }Gd|G }(tG| |(})tH| |(}*|)r|*r|)|*| d|+ < t d  d|) d|*  nt d  d|) d|*  qt dt
|+  dt|+ d t"d+  dht"d-< W 5 Q R X |+sZt d |	dkrtd|9ddfW S |	dkr,td|9ddfW S |	d6krHtddidfW S tddidfW S g },|D ]ĉ  |+krbtI|+  dd1d~D ]:\}-}.|.% rd  dt|-d  }/|,1|/|.d1d qt }ztjZd,dpi }HW n tk
r   i }HY nX |Hdpl|HdpltjMdpltjMdplttdrLtjdnd plttdrjtjdnd }5|5st|HtTr|Hdp|Hdpi }It|ItTr|Idp|Id}5|5rzt7j8N|5}5W n tk
r   Y nX |O|+|,|	||5d|r|d nd |	|r |d& nd }t"d+  |t"d5< W 5 Q R X t }7|7|
 P }8z|rd||	t|t|+|8|
 |7 |r|8t| ndd	| d#tjd$tj |	t|d%}|r|d&|d'< |d(|d)< |!| W n8 tk
r$ } zt dt|  W 5 d }~X Y nX qbtd,||+|9dW S W n tk
r } zrt jdt| d,d t[||	|tjd$dtj d t"d+  dht"d-< W 5 Q R X tdt|idZf W Y S d }~X Y nX d S )Nz === GENERATE ENDPOINT CALLED ===zRequest processed as JSONzFailed to parse JSON request: rG   zInvalid JSON requestr   zRequest processed as FormDatazRequest data type: zRequest data keys: NonezRequest files: zFile ru   z, size: readunknownr   ztestCaseTypes[]ZtestCaseTypesgetlistz)Please select at least one test case typer4   r5   r6   r7   r8   r9   Failed to verify auth token: zNo request data receivedZ
sourceTypezSource type is requiredZgenerate_button_clickZitemId)r   r   
item_countgeneration_start_time
session_idr   
event_type
event_datar&  r   
ip_addressr   r   r$  r:   user_idr<   	user_rolez'Failed to track generate button click: r  Tr  r  Zstartingr  r\   r  r  r  final_url_keyimagec                 s   s   | ]}d | V  qdS )image_NrR   r^   	test_typerR   rR   rS   rb     s     zgenerate.<locals>.<genexpr>r  r   c                 s   s   | ]}d | V  qdS )Zurl_NrR   r0  rR   rR   rS   rb     s     c                 3   s&   | ]} D ]}| d | V  q
qdS )r_   NrR   )r^   item_idr1  selected_typesrR   rS   rb     s       z === URL SOURCE TYPE DETECTED ===zReceived data: z[DEBUG] URL request received: 
url_configzURL from config: z[DEBUG] URL extracted: z[DEBUG] No URL found in requestURL is requiredz%[DEBUG] Starting URL processing for: z[DEBUG] Invalid URL formatInvalid URL formatz#[DEBUG] Testing URL accessibility: r   zsMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36)timeoutr>   z[DEBUG] URL response status: r   i,  z$[DEBUG] URL not accessible, status: zURL returned status z, but continuing anywayz[DEBUG] URL access error: zCould not access URL: z"[DEBUG] Importing URL generator...generate_url_test_casesz#Successfully imported URL generatorz+[DEBUG] URL generator imported successfullyzError importing URL generator: z[DEBUG] Import error: r   Zdashboard_functionalzSelected types from request: zTest case types to generate: z[DEBUG] Test case types: z[DEBUG] Generated URL key: z/[DEBUG] Starting async URL generation thread...c                 S   s  zt d|  d|  td t }td " dtd< td d|   W 5 Q R X t d	 d
dlm} t d|   td " dtd< td d|  W 5 Q R X || |}tdt	|  |st
dd| d}tjtjtd}tj|dd tj||}	t|	ddd,}
|
d|  d |
d |
| W 5 Q R X d| }t||}td|  |d| ||	dt d}zt }td t| d!|rt|nd
  td"|r|d d# nd$  t|}td%t| d!|r
t|nd
  |rt|D ]t\}}|d&g }td'|d(  d)|d*d+ d,t| d- |rtd.|d
   ntd/|d(   q"t|trtd0|d d1   d2d3d4d5d6gd7d8g}n$t|tstd9t|  g }| |d| ||d:|d|}td;|  W nh t!k
r } zHtd<|  td=t|  d
d l"}td>|#   |}W 5 d }~X Y nX zlt }|| $ }d?|d|d(d(||% |% |d@	d dAdBd|d(dC}|r||dD< |&| tdE W n4 t!k
r0 } ztdF|  W 5 d }~X Y nX td T t'tdG tdH< dItdJ< dKtdL< dtd< td dM |tdN< tdO|  W 5 Q R X W nl t!k
r } zLtdP|  td * dItdJ< dQtd< td dR|  W 5 Q R X W 5 d }~X Y nX d S )SNz [DEBUG ASYNC] Starting for URL: z	, types: z2[URL ASYNC] Starting direct URL content generationr  Zfetching_contentr  r  zFetching content from z([DEBUG ASYNC] Importing URL generator...r   r9  z%[DEBUG ASYNC] Fetching content from: Zai_generationz2Generating test cases from URL content for types: z9[URL ASYNC] Direct URL generation finished, has content: z.Failed to generate test cases from URL contentZurl_test_cases_.txtr   Texist_okwutf-8encodingzURL: 
z9Generated Test Cases (via direct URL content analysis):

z"[URL ASYNC] Generated Excel file: r   	completed)url_keyr   r   r   Zcontent_filer  r   z-[URL ASYNC] About to parse test cases. Type: z
, Length: z+[URL ASYNC] First 500 chars of test cases: r   r  z$[URL ASYNC] Parsed test data. Type: Stepsz[URL ASYNC] Test case r7   z 'Titler   z' has z stepsz[URL ASYNC] First step: z)[URL ASYNC] No steps found for test case zJ[URL ASYNC] parse_traditional_format returned a string instead of a list: r   ZGeneralzGenerated Test CasezTest scenario from URL contentzStep 1: Navigate to the URLzStep 2: Verify contentz+Content should be accessible and functional)ZSectionrF  ScenariorE  Expected Resultz?[URL ASYNC] parse_traditional_format returned unexpected type: )
test_casesr   r   r   r   z*[URL ASYNC] Saved test case with URL key: z&[URL ASYNC] Failed to save test case: z[URL ASYNC] Exception type: z[URL ASYNC] Full traceback: test_case_generated	rD  r   r   r$  Zfiles_generatedZgeneration_duration_secondsr%  generation_end_timeZaverage_time_per_itemzURL Generator	127.0.0.1r'  r+  z2[URL ASYNC] Tracked URL test case generation eventz6[URL ASYNC] Failed to track URL test case generation: r  r  Fr  d   r  zGeneration completedr-  z4[URL ASYNC] Set final_url_key in generation status: z[URL ASYNC] Error: rG   Error: )(printrF   r   r+   r   generation_statusr   r   r:  r  RuntimeErrorrw   rx   rg   dirname__file__makedirsopenwriter&   r   r)   typelenr(   	enumerater?   r   
isinstancerC   rG   r   save_test_caserE   	traceback
format_exctotal_secondsr  track_eventset)Z
target_urltypesZ
result_keyr+  r%  r:  Ztest_cases_localZtest_cases_filename_localZuploads_dirZtest_cases_filepath_localrQ   file_base_name
excel_fileZ
task_localZmongo_handler_localstructured_test_datair   stepsZurl_key_finalmer]  rL  generation_durationr)  Ztracking_errorZgen_errrR   rR   rS   _run_url_generation_async.  s    






	("(.
  
"

z+generate.<locals>._run_url_generation_asyncZqueuedzQueued URL generation for z with types: )r   rH   r   rD  FzFailed to access URL: zError processing URL content: z"=== IMAGE SOURCE TYPE DETECTED ===zRequest form data: Z	imageFilezNo imageFile in request.fileszNo image file uploadedzImage file received: zEmpty filename receivedzNo selected file%Y%m%d_%H%M%Sr_      r   Zimagesr<  r/  r#   zGenerating z test cases from imager3  

zFailed to generate zError generating z test cases from image: exc_infoapi keyZauthorizationr   r   z test cases: z(Failed to generate test cases from imageZmodel_not_foundZinvalid_request_errorzThe OpenAI model required for image processing is not available or has been deprecated. Please check your OpenAI account access.zJOpenAI API authentication failed. Please check your API key configuration.Ztest_image_)txtexcelz	TC_KAN-1_   )r   contentr  default_sectioncodegen_filecodegenFilefile)rI  r   image_idr   r   rw  rJ  rK  z,Failed to track image test case generation: )r8   rD  r   zFailed to save test case fileszImage processing error: zN. Please ensure the image is clear and in a supported format (JPG, PNG, JPEG).ziThe OpenAI model required for image processing is not available. Please check your OpenAI account access.quota
rate limitzBOpenAI API quota exceeded or rate limited. Please try again later.jiraz$Processing request for source_type: zRaw item_ids from request: zProcessed item_ids: z	 (count: )zSelected test types: zLarge batch detected: z  items. Processing in batches...   zMedium batch detected: z items.zSmall batch: zProcessing item_id: jira_configz!Fetching Jira issue for item_id: zFailed to fetch Jira issue for zVFailed to fetch Jira issue. Please check your credentials and ensure the issue exists.zJira connection error for zJira connection error: z Successfully fetched Jira issue r   r   fieldsr   summaryzIssue c              
      s   zVt | tr| W S t | trTd| krTg   fdd|  ddd  D W S W n8 tk
r } ztd d|  W 5 d }~X Y nX d	S )
Nrt  c                    sb   t | tr| dnd }|dkr6d| kr6 | d  t | trL| dg ng D ]}| qPd S )NrX  textrt  )r[  r   r?   r   )nodeZ	node_typechildZ
text_partsr|   rR   rS   r|   '  s
    z=generate.<locals>.extract_jira_description_text.<locals>.walkrB  c                 S   s   g | ]}|r|qS rR   rR   )r^   r   rR   rR   rS   
<listcomp>.  s      zCgenerate.<locals>.extract_jira_description_text.<locals>.<listcomp>z%Failed to parse Jira description for ru   r\   )r[  rC   r   rg   rE   rF   r   )descr   )r2  r  rS   extract_jira_description_text  s    
(z/generate.<locals>.extract_jira_description_textz test cases for )r   r  r4  rN  zProgress update: r   z = z.1f%zSuccessfully generated zNo test cases generated for z for azurez=== AZURE SECTION ENTERED ===azure_configzAzure config received: zAzure config type: zAzure config keys: z
Not a dictzAzure config values: zUsing frontend Azure config: )r  z,Using environment variables for Azure configzReason: azure_config exists: z, all values present: 
last_errorz,Failed to fetch work item from Azure DevOps.zAzure client error for item zAzure DevOps connection error: titlez%No test cases generated for item_id: z, skipping file creationzGenerated test cases for z, saving files...c                 s   s"   | ]}|  s|d kr|V  qdS ))-r_   N)isalnumr^   crR   rR   rS   rb     s       test_)rq  rr  rI  zSuccessfully saved files for z: txt=z, excel=zFailed to save files for zFinal results: z	 (total: z items)z%No results generated for any item IDsz7No Azure DevOps work items were successfully processed.)rG   errors_by_itemz+No Jira issues were successfully processed.zTFailed to process the uploaded image. Please ensure the image is clear and readable.zEFailed to generate test cases. Please check your input and try again.rI  ZTC_Zsilentform
user_inputZ	userInput)r   rI  r   item_idsr   rw  z&Failed to track test case generation: )r8   rD  r   r  zError during generation: )r   r4  r  r   r*  )N)\rF   r   r   is_jsonjsonrE   rG   r   r  rX  r   keysr   itemsfilenamer   rY  r   seekr?   r"  r[  rC   r>   r@   rA   r)   rB   r   r+   r   r  remote_addrr`  rQ  ra  rP  stripr/   allschemenetlocrequestsstatus_coder   r:  uuidZuuid4r   r   r   r   RequestExceptionr   r   rw   rx   rg   rS  rT  rU  splitextsaveai.image_generatorr$   r~   add
ValueErrorr   r{   r   r%   r&   rZ  r'   r(   extendrH   r   r\  r_  copyr   r!   r   valuesr    r  Zfetch_azure_work_itemsr  get_jsonr   )JdatarO   r   ry  rD   rJ   rK   rL   	user_infor   r%  r)  r  r5  r   
parsed_urlresponseZ	url_errorr:  Zimport_errorr   r  rD  r   rj  Z
image_fileZ	unique_idZimage_storageZfile_extZstored_filenameZ
image_pathr$   rI  Zall_types_processedZerror_messagesr1  Ztype_test_caseZcompletion_keyr   msgrc  txt_filerd  r  Zformatted_test_casesidxr   r   Ztest_case_sectionsre  section_namesection_contentparsed_casesZcodegen_file_in_osrL  ri  r  r  issuer  Zraw_descriptionZsummary_textr  Zdescription_textZprogressr  azure_client
work_items	error_msg	work_itemZsafe_filenameZreq_jsonr  rR   )r2  r4  rS   generatel  sl   
*
 6
&
$
$&



$

 $
0
 
$,
0
6



0

(








0





4
  

&




$$$,







: 


((
,



:



 $






"



  	

*
r  z/api/download/<path:filename>c              
      s  z.zNt  }d| d| kr&| dd nddtjdtjd g dd}|| W n6 tk
r } zt	d	t
|  W 5 d }~X Y nX tjt}tj|d
d}tj|stj|dd td|  tj|| }td|  tj|st	d|  td|  g }tj|rTt|D ]}| |kr8|| q8|r|d } tj|| }td|   n"t	d|   tddidfW S tjd}	tjd}
|	r| drzt|	}td|  dd l}||}d}| D ]@\}}|dd}|r||kr|| |j|df< |d7 }qtd| d  | d! |j d"d# |
rt d|
d$}nt dd%}t  fd&d'}W nV tk
r } z6t	d(|  |
rt|d|
d$}nt|dd%}W 5 d }~X Y nX nh|	rJ| d)rJzt|	}td*|  t!|d+d,d-}|" }W 5 Q R X | d. t! d/d,d-J}|#| |#d0 |$ D ]&\}}|r|#| d1| d2 qW 5 Q R X |
rt d|
d$}nt dd%}t  fd3d'}W nV tk
rF } z6t	d4|  |
r*t|d|
d$}nt|dd%}W 5 d }~X Y nX n"|
r`t|d|
d$}nt|dd%}zhd5| d| kr| dd ndtj|rtj%|nd|
d6tjdtjd g dd}|| W n8 tk
r } zt	d7t
|  W 5 d }~X Y nX d8|jd9< d:|jd;< d<|jd=< |W S  tk
r| } z,t	d>|  tdt
|id?f W Y S d }~X Y nX d S )@NZfile_download_attempted.r!  )r  	file_typer   r   r(  r)  r   r*  r   r   r$  z"Failed to track download attempt: r   r   Tr<  Created generated directory: zAttempting to download file: File not found: zSearching for file in: Found matching file: zNo matching files found for: rG   File not foundr   r  r  .xlsxz(Updating Excel file with status values: rF  r\   Statusr7   zUpdated z rows with status valuesz
.temp.xlsxF)r   r   r   )r   c              
      sR   zt j rt   W n2 tk
rL } ztd|  W 5 d }~X Y nX | S NzError removing temp file: rw   rx   r{   r~   rE   rF   rG   r  rO   Ztemp_file_pathrR   rS   remove_temp_file  s    "z'download_file.<locals>.remove_temp_filez)Error updating Excel with status values: r;  z&Updating TXT file with status values: rr?  r@  z	.temp.txtr>  z

# STATUS VALUES
ru   rB  c              
      sR   zt j rt   W n2 tk
rL } ztd|  W 5 d }~X Y nX | S r  r  r  r  rR   rS   r    s    "z'Error updating TXT with status values: Zfile_download_successful)r  r  	file_sizecustom_filenamez%Failed to track successful download: z#no-cache, no-store, must-revalidateCache-Controlno-cachePragma0ExpireszError downloading file: r   )&r)   rA   r   r>   r?   r  r`  rE   rF   rG   rC   rw   rx   rS  rT  rg   r{   rU  r   r   r   r   rH   r   r  loadspandas
read_exceliterrowsatZto_excelr   r   rV  r   rW  r  getsize)r  rL   r)  rO   r   generated_dir	file_pathmatching_filesry  status_valuesr  status_dictpddfupdated_countr   rowr  r  r  rQ   rt  r  rR   r  rS   download_file4  s    
&



"



$ 
&


r  z/api/files/<url_key>c              
   C   s  zt d|   t }|jd| i}|sPt d|   tddidfW S g }d|krt|d tr|d }d|krt|d tr|d 	 D ]>\}}t|trd	|kr|
|d	  d
|kr|
|d
  qd|krt|d tr||d  |s|dd}|dd}|r|rtjtjtdd}tj|rt|D ]2}	||	krR|	dsx|	drR|
|	 qRt dt| d|  d|  td|iW S  tk
r }
 z:t jd|  dt|
 dd tdt|
idf W Y S d}
~
X Y nX dS )z+Get list of files associated with a URL keyzRequested files for URL key: rD  No document found for URL key: rG   Document not foundr   r   r   rr  rq  r   r\   r2  r   r   r  r;  zFound z files for URL key ru   z Error getting files for URL key Trn  r   N)rF   r   r)   r  r   rG   r   r[  r   r  r   r   r  r?   rw   rx   rg   rS  rT  r{   r   r   rY  rE   rC   )rD  rL   r   r   r   r2  	file_infor   r   r  rO   rR   rR   rS   get_files_for_url_key  sB    
" r  z/api/ai-content/<url_key>c                 C   sZ  zt d|   t }|jd| i}|sPt d|   tddidfW S d|krt|d tr|d }d|kr|d }t|t	rtd	|iW S t|t
rtd	d
dd |D iW S d|krt|d tr|d }d|krt|d tr|d  D ]\}}t|trd|krzrtjtjtdd}tj||d }tj|rt|ddd}	|	 }W 5 Q R X td	|iW   W S W n> tk
r }
 zt d|d  d|
  W 5 d}
~
X Y nX qt d|   tddidfW S  tk
rT }
 z:t jd|  dt	|
 dd tdt	|
idf W Y S d}
~
X Y nX dS )z&Get AI-generated content for a URL keyz"Requested AI content for URL key: rD  r  rG   r  r   r   rI  rt  rm  c                 S   s   g | ]}t |qS rR   )rC   )r^   itemrR   rR   rS   r  C  s     z"get_ai_content.<locals>.<listcomp>r   rq  r   r   r  r?  r@  zCould not read file ru   Nz!No AI content found for URL key: zNo AI content foundz%Error getting AI content for URL key Trn  r   )rF   r   r)   r  r   rG   r   r[  r   rC   r   rg   r  rw   rx   rS  rT  r{   rV  r   rE   r   )rD  rL   r   r   rt  r2  r  r   r  rQ   rO   rR   rR   rS   get_ai_content*  sD    

0r  z!/api/results/<url_key>/test-casesc                 C   sv  zt d|   t }|jd| i}|sPt d|   tddidfW S d|krxt|d trxtd|d iW S d|krt|d t	r|d }d|krt|d trt
|d d	krtd|d iW S d
|krt|d
 t	r|d
  D ]\}}t|t	rd|krztjtjtdd}tj||d }tj|rd	dl}||}	g }
|	 D ]L\}}i }|	jD ],}|| }||rd||< n|||< q~|
| ql|
rtd|
iW   W S W q tk
r } zt d|d  d|  W 5 d}~X Y qX qd|krt|d trzd	dlm}m} ||d }|rg }| D ] \}}|||d}|| qb|rtd|iW W S n"||d }|rtd|iW W S W n4 tk
r } zt d|  W 5 d}~X Y nX t d|   tddidfW S  tk
rp } z:t jd|  dt| dd tdt|idf W Y S d}~X Y nX dS )z!Get test cases data for a URL keyz"Requested test cases for URL key: rD  r  rG   r  r   r   rI  r   r   rr  r   r   NCould not read Excel file ru   r(   r'   ru  #Could not parse test cases string: z!No test cases found for URL key: zNo test cases foundz%Error getting test cases for URL key Trn  r   rF   r   r)   r  r   rG   r   r[  r   r   rY  r  rw   rx   rg   rS  rT  r{   r  r  r  columnsisnar   rE   r   rC   utils.file_handlerr(   r'   r  rD  rL   r   r   r2  r  r   r  r  r  recordsr   r  recordcolumnvaluerO   r(   r'   sectionsZall_parsed_casesr  r  Zsection_casesr  rR   rR   rS   get_test_cases_for_url_key_  sp    &


."r  z/api/ai-tests/<url_key>c                 C   sv  zt d|   t }|jd| i}|sPt d|   tddidfW S d|krxt|d trxtd|d iW S d|krt|d t	r|d }d|krt|d trt
|d d	krtd|d iW S d
|krt|d
 t	r|d
  D ]\}}t|t	rd|krztjtjtdd}tj||d }tj|rd	dl}||}	g }
|	 D ]L\}}i }|	jD ],}|| }||rd||< n|||< q~|
| ql|
rtd|
iW   W S W q tk
r } zt d|d  d|  W 5 d}~X Y qX qd|krt|d trzd	dlm}m} ||d }|rg }| D ] \}}|||d}|| qb|rtd|iW W S n"||d }|rtd|iW W S W n4 tk
r } zt d|  W 5 d}~X Y nX t d|   tddidfW S  tk
rp } z:t jd|  dt| dd tdt|idf W Y S d}~X Y nX dS )zGet AI test cases for a URL keyz Requested AI tests for URL key: rD  r  rG   r  r   r   rI  r   r   rr  r   r   Nr  ru   r  ru  r  zNo AI tests found for URL key: zNo AI tests foundz#Error getting AI tests for URL key Trn  r   r  r  rR   rR   rS   get_ai_tests_for_url_key  sp    &


."r  z/api/content/<path:filename>c              
   C   s  z,t d|   | dks$| d krHt d|  d tddidfW S tjt}tj|dd	}tj	|stj
|d
d t d|  tj|| }t d|  tj	|sLt d|  g }tj	|rt|D ]}| |kr|| q|r*|d } tj|| }t d|   n"t d|  tddidfW S | dr~dd l}dd l}dd l}t d|   z||}	t dt|	 dt|	j  tjd}
i }|
rz||
}t d|  W n4 tk
r } zt d|  W 5 d }~X Y nX g }|	 D ]\}}i }|	jD ],}|| }||rXd ||< n|||< q6|dd}|r||kr|| |d< d|krt|d tr|d }td|rt d |}d!d" |D }|r||d< || q$t d#|  d$t| d% |r4t|d&kr
t!|d " s
t #d' |j|d d(}t|d&kr
d)d" |j$d D }g }t%d&t|D ]d}i }t&|D ]F\}}|t|jk r|j$||f }||rd ||< n|||< q|| q|r
t d*t| d+|  |}td,|iW W S  tk
rz } zBt jd-|  d.t| d
d/ tdd0t| id1f W Y W S d }~X Y nX nzNt'|d2d3d4}|( }W 5 Q R X t d5|  d6t| d7 td,|iW W S  tk
r* } z>t d8|  d.t|  tdd9t| id1f W Y W S d }~X Y nX W nZ tk
r } z:t jd:|  d.t| d
d/ tdt|idf W Y S d }~X Y nX d S );NzRequested content for file: Z	undefinedzInvalid filename: ''rG   zInvalid filename providedr   r   r   Tr<  r  zLooking for file at: z+File not found at exact path, searching in r   r  r  r  r   r  zReading Excel file: z"Excel file read successfully with z rows and columns: r  z#Applying status values to content: zError parsing status values: rF  r\   r  rE  z^\d+\.z\n\s*\d+\.|\nc                 S   s   g | ]}|  r|  qS rR   )r  )r^   srR   rR   rS   r  j  s      z$get_file_content.<locals>.<listcomp>zConverted Excel file z to  recordsr7   z@No valid records found in Excel file, checking for column issues)headerc                 S   s   g | ]}t | qS rR   )rC   r  )r^   hrR   rR   rS   r  z  s     zManually extracted z records with headers: rt  zError processing Excel file ru   rn  zError processing Excel file: r   r  r?  r@  zSuccessfully read text file:  (z characters)zError reading text file zError reading text file: zError in get_file_content for ))rF   r   rG   r   rw   rx   rS  rT  rg   r{   rU  r   r   r   r  Znumpyr  r  rY  r   r  r   rH   r?   r  rE   r  r  r[  rC   researchrA   r   r  r   Zilocrh   rZ  rV  r   )r  r   r  r  r  ry  r  Znpr  r  r  r  rO   r  r   r  r  r  r  r  Z
steps_textrg  raw_datar>   Zmanual_recordsrf  jr  rQ   rt  rR   rR   rS   get_file_content  s    
 
"

&

 
46r	  z/api/update-statusc                  C   sR  zt j} td|   | d}| d}| d}| dd}|sZtddid	fW S |sptdd
id	fW S |stddid	fW S | dkrtddid	fW S t }|j	d|i}|sd| }t
| td|idfW S ||||}|r|jd|idd| |d| t dt ii}	|rd|krt|d trt|d D ]R\}
}|d|krZ|jd|idd|
 d|ii td|
   qqZtd| d tddiW S d| d| }t
| td|idfW S W nP tk
rL } z0t
d t|  tdt|id!f W Y S d }~X Y nX d S )"Nz Received status update request: r   r   r  Zshared_viewFrG   zMissing required parameter: keyr   z(Missing required parameter: test_case_idz"Missing required parameter: statusr\   zStatus cannot be emptyrD  z No document found with url_key: r   $setzstatus.zstatus_timestamps.status_updated_atr   rF  
test_data..Statusz(Updated status in test_data array index z+Successfully updated status for test case 'r  r8   Tz&Failed to update status for test case z in document zError updating status: r   )r   r  rF   r   r?   r   r  r)   r  r   rG   Zupdate_test_case_status
update_oner+   r   r[  r   rZ  rE   rC   )r  rD  r   r  is_shared_viewrL   r   r  r8   resultrf  tcrO   rR   rR   rS   update_status  sh    




    

r  z
/api/sharec               
   C   s  z^d } t jd}|r|drz8|dd }t }||}|rX|drX|d } W n6 tk
r } zt	dt
|  W 5 d }~X Y nX t jrt j}nPt j }| D ]<\}}t|t
r|drzt|||< W q   Y qX qtd	|  |d
}	|d}
|dg }|di }|d}|	sNtddidfW S t }|svtd tddidfW S |rt|dkr||	t|dkr|d n||| r| d nd }n||	|
|| r| d nd }|r@z&||| td| d|  W n4 tk
r> } ztd|  W 5 d }~X Y nX ddlm} t jdrndt jd }nt jdrt jdrt jdd}| d t jd }nTt jdrt jdd!st jdd"sdt jd }n
|d#}| d$| }td% td&t jd  td't jd  td(t jd  td)|  td*|  td+|  td,t j  td-t j  z^d.||t|	trt|	ndt||rt|ndd/t jd0t jd g dd1}| | W n8 tk
rN } ztd2t
|  W 5 d }~X Y nX td3||d4W S  tk
r } z0td5t
|  tdt
|idf W Y S d }~X Y nX d S )6Nr4   r5   r6   r7   r8   r9   r#  {zShare request data: r   r2  r  r  r   rG   zNo test data providedr   zMongoDB handler not initializedzDatabase connection errorr   r   r:   zSaved status values for ru   zError saving status values: )BASE_URLzX-Forwarded-Hosthttps://zX-Forwarded-ProtoZHosthttpsz://rM  	localhostr   z/view/zURL generation details:z  - X-Forwarded-Host: z  - X-Forwarded-Proto: z
  - Host: z  - BASE_URL from settings: z  - Selected base_url: z  - Generated share URL: z  - Request URL: z  - Request base URL: Zshare_created_successfully)rD  	share_urlZtest_data_countZhas_status_valuesZstatus_values_countr   r  z+Failed to track successful share creation: T)r8   r  rD  zError in share_test_case: )!r   r>   r?   r@   rA   r)   rB   rE   rF   r   rC   r  r  r  to_dictr  r[  r  r   r   rG   rY  r\  Zupdate_status_dictconfig.settingsr  rstripr   base_urlr   r  r  r`  )rD   rJ   rK   Zauth_mongo_handlerr  rO   r  r   r  r   r2  r  r  r   rL   rD  r  r  protocolr  r)  rR   rR   rS   share_test_case  s    
&




6"6


&
r  z/view/<url_key>c              
   C   st  zzBt  }d| tjdddtjdtjd g dd}|| W n6 tk
r| } zt	dt
|  W 5 d }~X Y nX tjdd	 }|d
k}|| }|s|rtddidfW S tddfW S | |d< d|kr*t|d trtd|  dt|d  d nt|d tr\d|d kr\|d d |d< tdt|d  d nt|d tr*d|d kr*zt|d di }|d}|r tjtjtdd|}	tj|	r dd l}
|
|	}|d}||d< tdt| d t|d tsd|kr|d}|rtjtjtdd|}tj|rt|ddd }| }W 5 Q R X dd!lm }m!} ||}g }|r|" D ] \}}|||d"}|#| qn||}|r||d< td#t| d W n8 tk
r( } zt	d$t
|  W 5 d }~X Y nX d%|krt|d% trt|d tr|d% }|d&i }|d D ]L}d'|krp|d' |krp||d'  |d(< |d' |krp||d'  |d)< qp|rd*|krt
|d* |d*< t|W S td+|d,W S W nv tk
rn } zVtj	d-t
| d.d/ |d
krJtdt
|id0f W Y S tddf W Y S W 5 d }~X Y nX d S )1NZshared_page_visitedr.   html)rD  r.   r   r   r  z!Failed to track view page visit: r\   r  rG   Test case not foundr   z404.htmlr   r   zTest data for z is already a list with  itemsrI  z Extracted test_cases array with r   rr  r   r   r  zParsed Excel file into r  rq  r  r?  r@  )r'   r(   ru  zParsed text file into z!Error processing files for view: r  r  rF  r  ZStatusUpdatedAtr   z	view.html)r   z Error in view_shared_test_case: Trn  r   )$r)   r   rH   r?   r>   r  r`  rE   rF   rG   rC   r   get_test_caser   r   r[  r   r   rY  r   rw   rx   rg   rS  rT  r{   r  r  r  rV  r   r  r'   r(   r  r  )rD  rL   r)  rO   Zformat_paramZ	want_jsonr   r   rd  Z
excel_pathr  r  Zstructured_datar  Ztxt_pathrQ   Ztxt_contentr'   r(   r  r  r  r  r  r  r  rR   rR   rS   view_shared_test_caseh	  s    
&

$



&*


r#  z/api/shared/excel/<url_key>c              
   C   s  zvt | }|s$tddidfW S tjd}tjd}i }|rz(||}tdt	| d|  W q t
k
r } ztd|  W 5 d }~X Y qX n
td	 |s|d
rd|d
  d}nd| d d  d}|d
rd|d
  }nd| d d  }|d }dd l}d}	t }
d}|D ]b}|	d7 }	d|krb|dd}|	d| d7 }	d|kr|	d|dd d7 }	d|kr|dd}|	d7 }	t|trt|D ]"\}}|	|d  d| d7 }	qn|	d| d7 }	d|kr|	d|dd d7 }	|dd}d}|rJ||krJ|| }|
| |d7 }n|dd}|	d | d!7 }	d"|kr|	d#|d"d d7 }	|	d!7 }	q.td$| d% |	d&7 }	| D ]$\}}|r|	| d'| d7 }	q|	}dd(lm} |||}|stdd)id*fW S tjtjtd+d,|}t|d-|d.}d/|jd0< d1|jd2< d3|jd4< t||jd5< tt |jd6< |W S  t
k
r } z0td7t|  tdt|id*f W Y S d }~X Y nX d S )8NrG   r   r   r  r  zSHARED EXCEL: Received z status values: z+SHARED EXCEL: Error parsing status values: z'SHARED EXCEL: No status values providedr2  r  r  Ztest_shared_rl  r   r   r\   zTEST CASE:
rF  zTitle: rB  rG  z
Scenario: rE  zSteps to reproduce:
r7   z. z1. rH  zExpected Result: r  zStatus: rm  ZPriorityz
Priority: zSHARED EXCEL: Updated z test cases with status valuesz

# STATUS SUMMARY
ru   )r&   zFailed to generate Excel filer   r   r   Tr  .no-cache, no-store, must-revalidate, max-age=0r  r  r  r  r  zX-Status-Updated-CountzX-Status-Update-TimezError generating Excel file: )rL   r"  r   r   rH   r?   r  rF   r   rY  rE   rG   r  ra  r[  r   rZ  r  r  r  r&   rw   rx   rg   rS  rT  r   r>   rC   r+   r   )rD  r   r  r  r  r  rO   rc  r   Zformatted_dataZstatus_updatedr  r  r  rg  rf  stepr  Ztest_data_strr&   rd  r  r  rR   rR   rS   download_shared_excel	  s    

$














r&  z/api/generation-statusc                  C   s0  zt d  d} t d r4tt d tt d  d } t| sF| dk rLd} n| dkrXd} t d tt d tt d | t d  t ddt d	dtt d
g t ddd	}td|d   W 5 Q R X t|W S  t	k
r* } z6t
dt|  tt|dddddf W Y S d }~X Y nX d S )Nr  r   r  r  rN  r  r  r\   r  r  r-  )	r  r  r  r  files_readyr  r  r  r-  z,Generation status response - final_url_key: z!Error getting generation status: FT)rG   r  r  r'  r   )rQ  rY  mathisnanr   r?   rF   r   r   rE   rG   rC   )r  r  rO   rR   rR   rS   get_generation_statusV
  s0    






r*  z/api/shared-statusGETc               
   C   s  zt jd} t jdd dk}| s<tddidfW S td|   t }|j| d	d
}|d krztddidfW S d	|t	t
 d}|r||jd| i}|r|||d< d|kr|d|d kr|d d |d< |d d }|rnt| }td|  ||d< d|kr |d= d|d krT|d d |d< td|d   nd|d< td ||d< z4ddlm} g }	| D ]\}
}td|
  d|krTt|d t	rT|d }td|
 dt| d ||}|rB|D ](}d |kr|d   d!|
 d|d < q|	| td"t| d#|
  ntd$|
  ntd%|
  q|	r|	|d< td&t|	 d' t|W W S td( W nP tk
r } z0td)|  dd l}td*|   W 5 d }~X Y nX nhd|krt|d trtd+|dd, d- |d |d< |dd.krxd.|krx|d. g|d< td/|d.   n$|dd0krd1g|d< td2 ||d< td3t|d  d4 t|W S d|krbt|d trbtd5|dd, d- |d }|dd6krd|kr|d d.krtd7 d|krbt|d trb|d |d< |d |d< |d.d8|d.< |d.d8g|d< ||d< td3t|d  d9 t|W S n|dd:krbd|krb|d d0krbtd; d|krbt|d trb|d |d< |d |d< |d<d8|d<< d1g|d< ||d< td3t|d  d= t|W S d|d kr`t|d d tr`|d d }td>t| d? g }|D ]}t|trd@|kr|d@d8}|rt|t	rddlm} ||}|r|| n*|dAdBdCdDdE|dFdGdH}|| q|r|||d< tdIt| dJ nt|d tr||d |d< t|}dK|jdL< dM|jdN< dO|jdP< |W S  tk
r } z0tdQt	|  tdt	|idRf W Y S d }~X Y nX d S )SNr   ZincludeFilesfalserY   rG   Missing URL key parameterr   z$Fetching shared status for URL key: T)Zforce_refreshr   r   )r8   r  r   rD  r  r   r   zExtracted item IDs from files: r  r2  r   zAdded source_type to document: ZJirazUsing default source_type: Jirar   )r(   zProcessing file: rI  zFound test cases content for z
 (length: r~  rF  r  zSuccessfully parsed z test cases from zNo test cases parsed from zNo test_cases string found in zSuccessfully combined z  total test cases from all filesz No test cases found in any filesz%Error parsing test cases from files: Traceback: z Found direct test_data list for r!  z source typer   zSet URL as item_id: r.  zUploaded Imagez!Set Image item_id: Uploaded ImagezSuccessfully loaded z! test cases from direct test_dataz Found nested test_data dict for )Nr\   r   z$Found URL data with nested structurer\   z% URL test cases from nested structure)Nr\   r.  z&Found Image data with nested structurerz  z' Image test cases from nested structurezFound test_cases list with r!  rt  r   r   zScenario extracted from contentzSteps extracted from contentz&Expected result extracted from contentr  z
Not Tested)rF  rG  rE  rH  r  zSuccessfully converted z% test cases from test_cases structurer$  r  r  r  r  r  z Error retrieving shared status: r   )r   rH   r?   r   r   rF   r   r)   Zget_test_case_status_valuesrC   r+   r   r  r   r   r  r  r(   r  r[  rY  r  r   rE   r]  r^  r   r   r>   rG   )rD  Zinclude_filesrL   r  response_datar   Z
files_datar  r(   all_test_casesZfile_keyZ	file_dataZtest_cases_contentZparsed_test_casesr  rO   r]  Znested_test_dataZtest_cases_listZconverted_test_casesrt  parsedr   r  rR   rR   rS   get_shared_statusv
  s   





*








"




r2  z/api/analytics/trackc            
      C   s~  z&t j} | s tddidfW S | d| di | dt jdt j| d| d	g | d
dd}t jd}|r|drzT|dd }t }|	|}|r|dr|d }|d|d< |d|d< W n t
k
r   Y nX t }||}|rtdddW S tddidfW S W nP t
k
rx }	 z0tdt|	  tdt|	idf W Y S d}	~	X Y nX dS )z"Track user events and interactionsrG   No data providedr   r(  r)  r&  r   r   r   r$  r   r'  r4   r5   r6   r7   r8   r9   r:   r+  r<   r,  TzEvent tracked successfullyr8   r   zFailed to track eventr   zError tracking analytics: N)r   r  r   r?   r>   r  r@   rA   r)   rB   rE   r`  rF   rG   rC   )
r  r)  rJ   rK   mhverificationZ
event_userrL   r8   rO   rR   rR   rS   track_analyticsP  sB    





r7  z/api/analytics/sessionc            
   
   C   sr  zt j} | s tddidfW S | dt jdt jt jd| d| d| d	d
}t jd}|r|drzT|dd }t }|	|}|r|dr|d }|d|d< |d|d< W n t
k
r   Y nX t }||}|rtdddW S tddidfW S W nP t
k
rl }	 z0tdt|	  tdt|	idf W Y S d}	~	X Y nX dS )z"Track user session and page visitsrG   r3  r   r&  r   ZRefererpage_visitedcountrycity)r&  r   r*  Zreferrerr8  r9  r:  r4   r5   r6   r7   r8   r9   r:   r+  r<   r,  TzSession tracked successfullyr4  zFailed to track sessionr   zError tracking session: N)r   r  r   r?   r>   r  r@   rA   r)   rB   rE   Ztrack_user_sessionrF   rG   rC   )
r  Zsession_datarJ   rK   r5  r6  r9   rL   r8   rO   rR   rR   rS   track_session~  s@    



r;  z/api/analytics/summaryc               
   C   s~  z&t jd} t }d}| rp| drpz2| dd }||}|rX|drX|d }W n tk
rn   Y nX |stdd	d
dfW S t j	d}t j	d}t j	d}t j	jddt
d}|}	|ddkr|	j||||d}
n|	j|||||dd}
|
rtd|
dW S tddidfW S W nP tk
rx } z0tdt|  tdt|idf W Y S d}~X Y nX dS )zMGet analytics summary with RBAC: admin gets system-wide, users get their own.r4   Nr5   r6   r7   r8   r9   FAuthentication requiredr4    
start_dateend_dater   rp   rn   )rX  r<   admin)r>  r?  rp   r   r:   )r>  r?  rp   r   r+  Tr8   r  rG   zFailed to get analytics summaryr   z!Error getting analytics summary: )r   r>   r?   r)   r@   rA   rB   rE   r   rH   intget_analytics_summaryrF   rG   rC   )rJ   r5  rD   rK   r  r>  r?  r   rp   rL   r  rO   rR   rR   rS   rC    sN    
rC  z/api/analytics/detailedc               
   C   sr  zt jd} | r| ds2tddddfW S t }| dd }||}|rp|d	rp|d
 ddkrtddddfW S i }t jd}|rz8t	|dkrt
|d|d< nt
|dd|d< W n, tk
r   t
|dd d|d< Y nX t jd}|rzRt	|dkrJt
|dtdd tdd }||d< nt
|dd|d< W nF tk
r   t
|dd dtdd tdd }||d< Y nX t jd}|r||d< t jd}	|	r|	|d< t }
|
|}|dk	rtd|dW S tddidfW S W nP tk
rl } z0tdt|  tdt|idf W Y S d}~X Y nX dS ) z0Get detailed analytics with filters. Admin only.r4   r5   Fr<  r4  r=  r6   r7   r8   r9   r<   r@  	Forbidden  r>  r   %Y-%m-%dZ+00:00Nr?  ro   )Zmillisecondsr(  r   TrA  rG   z Failed to get detailed analyticsr   z"Error getting detailed analytics: )r   r>   r?   r@   r   r)   rA   rB   rH   rY  r+   strptimefromisoformatreplacerE   r,   get_detailed_analyticsrF   rG   rC   )rJ   r5  rK   r6  filtersr>  r?  Zend_dtr(  r   rL   eventsrO   rR   rR   rS   rL    sT    
  
(

rL  z/api/test-cases/recentc               
   C   s>  zt jd} | r| ds0tddddfW S t }| dd }||}|r\|d	sptdd
ddfW S |d d }|j|dd}|r|D ]4}d|krt	|d |d< d|kr|d 
 |d< qtd|dW S tdg dW S W nN tk
r8 } z.tdt	|  tddddf W Y S d}~X Y nX dS )z0Get recent test cases for the authenticated userr4   r5   Fr<  r4  r=  r6   r7   r8   Invalid tokenr9   r:   r   )r   r   r   T)r8   rI  z!Error getting recent test cases: zFailed to retrieve test casesr   N)r   r>   r?   r@   r   r)   rA   rB   get_user_test_casesrC   r  rE   rF   rG   )rJ   r5  rK   r  r+  rI  r  rO   rR   rR   rS   get_recent_test_cases$  s8    

rQ  z/api/analytics/errorsc               
   C   s  z|t jd} | r| ds2tddddfW S t }| dd }||}|rp|d	rp|d
 ddkrtddddfW S ddlm	} t j
d}t j
d}t j
d}|r,|r,z0t|d}t|d}	|	| j}
t|
d}W n8 tk
r( } ztd|  d}W 5 d}~X Y nX ntt j
dd}|j||||d}d|krptd|d idfW S td|dW S  tk
r } z0tdt|  tdt|idf W Y S d}~X Y nX dS )z-Get error analytics from MongoDB (admin only)r4   r5   Fr<  r4  r=  r6   r7   r8   r9   r<   r@  rD  rE  r   )error_loggerr>  r?  r-   rF  rn   z1Error parsing date range, using default 30 days: Nrp   )rp   r-   r>  r?  rG   r   TrA  zError getting error analytics: )r   r>   r?   r@   r   r)   rA   rB   utils.error_loggerrR  rH   r+   rI  rp   maxrE   rF   r   rB  Zget_error_summaryrG   rC   )rJ   r5  rK   r6  rR  r>  r?  r-   Zstart_datetimeZend_datetimeZ	days_diffrp   rO   Zerror_summaryrR   rR   rS   get_error_analyticsO  sF    
 

rU  z/api/mongo-document/<url_key>c              
   C   s
  z| st ddidfW S td|   t }|jd| i}|sR|jd| i}|sht ddidfW S d|krt|d |d< d	|d
}t |}d|jd< d|jd< d|jd< |W S  tk
r } z0t	dt|  t dt|idf W Y S d}~X Y nX dS )z%Get MongoDB document content directlyrG   r-  r   z)Retrieving MongoDB document for URL key: rD  r   r  r   T)r8   r  r$  r  r  r  r  r  z#Error retrieving MongoDB document: r   N)
r   rF   r   r)   r  r   rC   r>   rE   rG   )rD  rL   r   r/  r  rO   rR   rR   rS   get_mongo_document  s.    


rV  z/api/notify-status-changec               
   C   s
  zt jd} t jd}t jd}| s<tddidfW S td|  d| d	|  tjd
| idt	
 ||t	
 ddi tddd}d|jd< d|jd< d|jd< |W S  tk
r } z0tdt|  tdt|idf W Y S d }~X Y nX d S )Nr   r   r  rG   r-  r   z,Received status change notification for key=z, testCaseId=z	, status=rD  r
  )r   r  r   )r  Zlast_status_changeTz#Status change notification receivedr4  r$  r  r  r  r  r  z-Error processing status change notification: r   )r   rH   r?   r   rF   r   rL   r  r  r+   r   r>   rE   rG   rC   )rD  r   r  r  rO   rR   rR   rS   notify_status_change  s:    


rW  z/api/debug/force-syncc            
   
   C   st  zt jd} | s&tddidfW S t }|jd| i}|sRtddidfW S t|dt}i }|rt	|d D ],\}}|d	d
}|dd
}|rv|||< qvt	|d D ]B\}}|d	d
}||kr|j
d| idd| d|| ii qnd|krd|d krt	|d d D ]@\}}|d	|dd
}|d|dd
}|r|||< qt	|d d D ]N\}}|d	|dd
}||krp|j
d| idd| d|| ii qp|r|j
d| idd|ii |j
d| idt |ddd di tdd||dW S  tk
rn }	 z0tdt|	  tdt|	idf W Y S d}	~	X Y nX dS )z;Debug endpoint to force sync of status values between viewsr   rG   r-  r   rD  r  r   r   rF  r\   r  r
  r  r  rI  r  r  ztest_data.test_cases.z.statusstatus_force_sync_countr   r7   )Zstatus_force_synced_atrX  TzStatus values forced to sync)r8   r   r  r  zError during force sync: r   N)r   rH   r?   r   r)   r  r   r[  r   rZ  r  r+   r   rE   rF   rG   rC   )
rD  rL   r   r  Zupdated_statusrf  r  r  r  rO   rR   rR   rS   debug_force_sync  sr    



rY  z/healthc               
   C   s8  zd} zt rt j  nd} W n0 tk
rN } zdt| } W 5 d}~X Y nX d}z:tjt}tj	|dd}tj
|stj|dd W n0 tk
r } zdt| }W 5 d}~X Y nX td	t  | |td
rdnddW S  tk
r2 } z(tdt|t  ddf W Y S d}~X Y nX dS )z*Health check endpoint for cloud deploymentZOKzNot initializedrO  Nr   r   Tr<  ZhealthyZRENDER
productionZdevelopment)r  r   mongodbZ
filesystemZenvironmentZ	unhealthy)r  rG   r   r   )rL   r  r   rE   rC   rw   rx   rS  rT  rg   r{   rU  r   r+   r   r  getenv)Zmongo_statusrO   Z	fs_statusr   r  rR   rR   rS   health_check8  s>      


r]  z/api/verify-api-keyc               
   C   s  ddl } ddl}z2ddlm} |r4|dks4|dkrJtdddd	d
fW S ddl m} ||d}z|j }|rdd |jD }dd |D }|rtdd|dW W S tddd|dd ddfW W S ntdddd	d
fW W S W n\ t	k
r@ } z<t
dt|  tddt| dd	d
f W Y W S d}~X Y nX W n t	k
r }	 zvt|	}
d}d|
 ksd |
 krd!}n&d"|
 krd#}nd$|
 krd%}tdd&|
 |d	d
f W Y S d}	~	X Y nX dS )'zJ
    Endpoint to verify if the OpenAI API key is configured correctly
    r   N)OPENAI_API_KEYZyour_openai_api_key_heremissing_api_keyrG   z$OpenAI API key is missing or invalidzWPlease configure a valid API key in your .env file. The API key should start with "sk-")r  r   detailsr   OpenAIapi_keyc                 S   s   g | ]
}|j qS rR   )r:   r^   modelrR   rR   rS   r  }  s     z"verify_api_key.<locals>.<listcomp>c                 S   s2   g | ]*}| d rd|ks*|d ks*|dkr|qS )zgpt-4oZvisiongpt-4o-mini)r@   re  rR   rR   rS   r  ~  s    
  r8   z0API key is valid and vision models are available)r  r   Zavailable_vision_modelsr   z3API key is valid but no vision models are availablez?Your OpenAI account may not have access to gpt-4o Vision modelsr   )r  r   r`  available_modelsr   zCould not validate API keyz4API responded without error but no data was returnedzError validating API key: zAPI verification failed: z5There was an error verifying your API key with OpenAIzHCheck that your API key is valid and your account has sufficient creditsZauthenticationrp  z'Invalid API key or authentication issuer|  zARate limited by OpenAI. Try again later or check your usage tier.r{  zNYou have exceeded your quota. Check your billing settings on OpenAI dashboard.zAPI key verification failed: )openair  r  r^  r   rb  Zmodelsr   r  rE   rF   rG   rC   r   )ri  r  r^  rb  clientr  rh  Zvision_modelsZ	api_errorrO   r   Zerror_detailsrR   rR   rS   verify_api_key_  s    



 rk  z/setup-helpc                   C   s   t dddS )z5Page with setup instructions and API key verificationr   z1This page helps you configure your OpenAI API keyr   r   rR   rR   rR   rS   
setup_help  s    rl  z/api/shorten-urlc               
   C   sf  zt j} td|   | s:td tddidfW S t }| d}| d}| d}|s~td tdd	idfW S |rt|d
krtd| d |j	
||dd}|rtd|d   tdd|d  iW S || }td|  tdd| iW S  tk
r` } z0tdt|  tdt|idf W Y S d }~X Y nX d S )Nz$Received URL params for shortening: zNo URL parameters providedrG   r   r   r   r  zNo files parameter in URL datazNo files parameter providedrl  zFound long key z!, checking for existing short URLZshortened_url)zurl_params.fileszurl_params.item_idsrX  zFound existing short URL: r   z/results?token=z"Generated new short URL with key: zError creating shortened URL: r   )r   r  rF   r   rG   r   r)   r?   rY  r  r   Zsave_url_datarE   rC   )r  rL   Zexisting_keyr   r  Zexisting_docr  rO   rR   rR   rS   shorten_url  sF    




 
 rm  z/api/verify-jirac               
   C   s.  zt j} | dd }| dd }| dd }|rD|rD|sXtddddfW S |d	sjd
| }ddlm} ||||}| }|rt	
d|dd  tdd|dddW S tddddfW S W nR tk
r( } z2t	dt|  tdt|ddf W Y S d}~X Y nX dS )z&Verify Jira connection and credentialsjiraUrlr\   jiraUser	jiraTokenFMissing required fieldsr8   rG   r   zhttp://r  r  r   
JiraClientz%Jira connection successful for user: ZdisplayNamer   TConnection successfulr8   r   r9   z Could not authenticate with Jirar=  zJira verification error: r   N)r   r  r?   r  r   r@   jira.jira_clientru  Zget_current_userrF   r   rE   rG   rC   )r  jira_url	jira_user
jira_tokenru  jira_clientr  rO   rR   rR   rS   verify_jira_connection  s.    


r}  z/api/test-urlc               
   C   s<  zt j} | dd }|s0tddddfW S ztt|}t|j|jgs`tddddfW W S t	j|dd	}|j
d
krtdddW W S tddd|j
fW W S W n< t	jk
r } ztddddf W Y W S d}~X Y nX W nR tk
r6 } z2tdt|  tdt|ddf W Y S d}~X Y nX dS )zTest if a URL is accessibler   r\   Fr6  rr  r   r7  r   r8  r   TzURL is accessibler4  zURL is not accessiblezFailed to connect to URLNzURL test error: r   )r   r  r?   r  r   r/   r  r  r  r  r  r  rE   rF   rG   rC   )r  r   r  r  rO   rR   rR   rS   test_url	  s$    
.r  z/api/verify-azurec            	   
   C   sD  zt j} | dd }| dd }| dd }| dd }|rX|rX|rX|sltdddd	fW S |d
s~d| }ddlm} ||||}||}|rt	
d|dd  tdd|dddW S tddddfW S W nR tk
r> } z2t	dt|  tdt|ddf W Y S d}~X Y nX dS )z.Verify Azure DevOps connection and credentialsazureUrlr\   azureOrgazureProjectazurePatFrq  rr  r   rs  r  r   r   z)Azure connection successful for project: r   r   Trv  )r8   r   projectz(Could not authenticate with Azure DevOpsr=  zAzure verification error: r   N)r   r  r?   r  r   r@   azure_integration.azure_clientr    get_projectrF   r   rE   rG   rC   )	r  	azure_url	azure_orgazure_project	azure_patr    r  project_inforO   rR   rR   rS   verify_azure_connection'  s0    



r  z/api/fetch-jira-itemsc                  C   s  zHt j} | dd }| dd }| dd }|rF|rF|sZtddddfW S |d	sld
| }ddlm} ||||}ddddg}|jd|d}|r4g }|D ]`}	|	|	dd|	di dd|	di di dd|	di di ddd qt
dt| d td|dW S tdddd fW S W n tk
r }
 zt
d!t|
  d"}z4ddl}t|
|jr|
jdk	r|
jjpd"}W n tk
r   Y nX tdt|
d|f W Y S d}
~
X Y nX dS )#z'Fetch recent Jira items for suggestionsrn  r\   ro  rp  Frq  rr  r   rs  r  r   rt  zTo DoReady for QAzReady for QazReady For QAN)r   Zstatusesr   r  r  Z	issuetyper   ZIssuer  r:   r  rX  r  Fetched z Jira items for suggestionsTr8   r  z%No issues found with provided filtersr   zError fetching Jira items: r   )r   r  r?   r  r   r@   rx  ru  Zget_recent_issuesr   rF   r   rY  rE   rG   rC   r  r[  	HTTPErrorr  r  )r  ry  rz  r{  ru  r|  Zdesired_statusesZissuesr  r  rO   r  r  rR   rR   rS   fetch_jira_itemsM  sT    



r  z/api/fetch-azure-itemsc                  C   s  zdt j} td|   | dd }| dd }| dd }| dd }td| d| d	| d
|rdt| nd  |r|r|r|stdt| dt| dt| dt|  t	ddddfW S |
dsd| }ddlm} ||||}||_td|  ||}|s^td|  t	dd| dddfW S td|d|  td | d! d"d#d$d%g}|j|d&|d'}	td(|	rt|	nd d) |	rPg }
|	D ]V}|
t|d*d|d+i d,d|d+i d-d.|d+i d/dd0 qtd1t|
 d2 t	d3|
d4W S t	dd5dd6fW S W n tk
r } zbtd7t|  td8t|  dd&l}td9|   t	dt|dd:f W Y S d&}~X Y nX d&S );z4Fetch recent Azure DevOps work items for suggestionszReceived Azure data: r  r\   r  r  r  zProcessed Azure fields - URL: 'z	', Org: 'z', Project: 'z', PAT: *r  zMissing Azure fields - URL: z, Org: z, Project: z, PAT: Frq  rr  r   rs  r  r   r   zTesting Azure project access: z Failed to access Azure project: zCannot access project z . Please check your permissions.rE  z%Successfully accessed Azure project: r   z'Fetching Azure work items for project: z with QA-ready filtersr  zRe-openZReopenedz	Re-openedN)r   Zstatesz
Retrieved z Azure work itemsr:   r  zSystem.TitlezSystem.WorkItemTypez	Work ItemzSystem.Stater  r  z! Azure work items for suggestionsTr  zNo work items foundr   zError fetching Azure items: zError type: r.  r   )r   r  rF   r   r?   r  rY  rG   r  r   r@   r  r    r  r  Zget_recent_work_itemsr   rC   rE   rX  r]  r^  )r  r  r  r  r  r    r  r  Zdesired_statesr  r  r  rO   r]  rR   rR   rS   fetch_azure_items  sf    22

 
r  z/api/export-excelc               
   C   s>  zt j} | stddidfW S | dg }| di }| dd}| dg }|sdtdd	idfW S td
t| d|  ddlm} |||||}t	
 d}d| d| d}ddlm}	 |	|ddd| did}
|
W S  tk
r8 } z6tdt|  tddt| idf W Y S d}~X Y nX dS )zExport test cases to Excel filerG   r3  r   rI  r  r   r   r  zNo test cases providedz
Exporting z test cases to Excel for r   )create_excel_reportrk  Ztest_cases_r_   r  ResponsezAapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetContent-Dispositionzattachment; filename=""r   r>   zError exporting to Excel: zExport failed: r   N)r   r  r   r?   rF   r   rY  r  r  r+   r   r   r   r  rE   rG   rC   )r  rI  r  r   r  r  Z
excel_datar   r  r  r  rO   rR   rR   rS   export_excel  s2    r  z/api/auth/signupc               
   C   sN  zt j} | s tddddfW S | dd }| dd }| dd}|r\t|d	k rptdd
ddfW S |r|d|krtddddfW S |rt|dk rtddddfW S t }||||}|d rtdddW S td|d ddfW S W nN tk
rH } z.t	
dt|  tddddf W Y S d}~X Y nX dS )zHandle user registrationFr3  r4  r   r   r\   r;   passwordrs  z'Name must be at least 2 characters long@$Please provide a valid email addressrl  z+Password must be at least 8 characters longr8   Tz-Account created successfully! Please sign in.r   zError in signup API: z%An error occurred during registrationr   N)r   r  r   r?   r  rY  r)   Zcreate_userrE   rF   rG   rC   )r  r   r;   r  rL   r  rO   rR   rR   rS   
signup_api  s0    
r  z/api/auth/signinc               
   C   s   zt j} | s tddddfW S | dd }| dd}|rD|sXtddddfW S t }|||}|d	 rtd
d|d |d dW S td|d ddfW S W nL tk
r } z.t	dt
|  tddddf W Y S d}~X Y nX dS )zHandle user loginFr3  r4  r   r;   r\   r  zEmail and password are requiredr8   TzLogin successful!rK   r9   )r8   r   rK   r9   r   r=  zError in signin API: zAn error occurred during loginr   N)r   r  r   r?   r  r)   Zauthenticate_userrE   rF   rG   rC   )r  r;   r  rL   r  rO   rR   rR   rS   
signin_api!  s*    
r  z/api/auth/logoutc               
   C   sR   zt jd} | r| ds2tddddfW S | dd }zDd	d
l}d	dlm} |j	||dgd}|d}t
d| d W nl |jk
r   t
d Y nP |jk
r   t
d Y n4 tk
r } zt
dt|  W 5 d
}~X Y nX tdddW S  tk
rL } z,t
dt|  tddddf W Y S d
}~X Y nX d
S )z"Logout user and invalidate sessionr4   r5   FzNo valid authorization headerr4  r=  r6   r7   r   N)rj   ZHS256)Z
algorithmsr+  zUser z logging outz(User attempted logout with expired tokenz(User attempted logout with invalid tokenzError verifying logout token: TzLogged out successfullyzLogout error: zLogout failedr   )r   r>   r?   r@   r   rA   jwtr  rj   decoderP  ZExpiredSignatureErrorZInvalidTokenErrorrE   rC   )rJ   rK   r  rj   payloadr+  rO   rR   rR   rS   
logout_apiD  sD    
$
r  z/api/auth/statusc               
   C   s  zt jd} | r| ds*tddiW S | dd }z`t }||}|r|dr|d }td	t|d
 |d |d |ddd|dW W S W n t	k
r   Y nX tddiW S  t	k
r } z(t
dt|  tddi W Y S d}~X Y nX dS )z7Check authentication status for desktop app integrationr4   r5   authenticatedFr6   r7   r8   r9   Tr:   r;   r   r<   r=   r  r9   rK   zError in auth status API: N)r   r>   r?   r@   r   rA   r)   rB   rC   rE   rF   rG   rJ   rK   rL   rM   rN   rO   rR   rR   rS   auth_status_apip  s2    



r  z/api/auth/check-sessionc               
   C   s   zt jd} | r| dr| dd }z`t }||}|r|dr|d }tdt|d |d	 |d
 |ddd|dW W S W n t	k
r   Y nX tddiW S  t	k
r } z(t
dt|  tddi W Y S d}~X Y nX dS )z=Check if user has an active session (for desktop app polling)r4   r5   r6   r7   r8   r9   Tr:   r;   r   r<   r=   r  r  FzError in check session API: N)r   r>   r?   r@   rA   r)   rB   r   rC   rE   rF   rG   r  rR   rR   rS   check_session_api  s0    



r  z/api/auth/desktop-tokenc               
   C   s
  zt  } ddlm}m} | |dd }| jjdd|dddgd	}|r| |d
 }td|d   t	dt
|d
 |d |d |ddd|dW S td t	ddiW S W nH tk
r } z(tdt
|  t	ddi W Y S d}~X Y nX dS )z(Get authentication token for desktop appr   r*   rq   ro   T)z$existsz$gte)	is_active
last_login)r  r  r   r   z"Desktop token generated for user: r;   r   r<   r9   r=   r  z-No recent active user found for desktop tokenr  FzError in desktop token API: N)r)   r+   r,   r   users_collectionr   generate_jwt_tokenrF   r   r   rC   r?   rE   rG   )rL   r+   r,   Zcutoff_timer9   rK   rO   rR   rR   rS   desktop_token_api  s6    



r  z/api/auth/desktop-sessionc               
   C   s  zt j} | r| ds*tddddfW S | d }t }||}|r|drdtd< |d	 d
 td< |d	 d td< dt_t	d|d	 d   tdd|d	 dW S tddddfW S W nN t
k
r } z.tdt|  tddddf W Y S d}~X Y nX dS )z:Create a persistent session for desktop app authenticationrK   FzToken requiredr4  r   r8   Tdesktop_authenticatedr9   r:   desktop_user_idr;   Zdesktop_user_emailz"Desktop session created for user: zDesktop session createdrw  rO  r=  zError in desktop session API: zSession creation failedr   N)r   r  r?   r   r)   rB   r   Z	permanentrF   r   rE   rG   rC   )r  rK   rL   r  rO   rR   rR   rS   desktop_session_api  s,    

r  c               
   C   s   zt drt } t d}|r| jdt|i}|r|ddr| |d }tdt|d |d |d |dd	d
|dW S tddiW S  t	k
r } z(t
dt|  tddi W Y S d}~X Y nX dS )zGet desktop app session statusr  r  r   r  Tr;   r   r<   r9   r=   r  r  Fz"Error in get desktop session API: N)r   r?   r)   r  r   r3   r  r   rC   rE   rF   rG   )rL   r+  r9   rK   rO   rR   rR   rS   get_desktop_session_api  s*    




r  z/api/configc                  C   s  z\t jddt jddddt jddit jd	dt jd
dt jdddt jddt jddt jddt jdddt jddt jddt jdddt jddt jddt jddt jddt jddt jdd dkt jd d! dkt jd"r:t jd"dd#ng d$d%} td&| t  d'W S  t	k
r } z2t
d(t|  td)t|d*d+f W Y S d,}~X Y nX d,S )-z-Get environment configuration for desktop appMONGODB_URIzmongodb://localhost:27017
MONGODB_DBZai_testcase_generator)uridbrd  r^  r\   ZJIRA_URLZ	JIRA_USERZJIRA_API_TOKEN)r   r9   Z	api_tokenZAZURE_DEVOPS_URLZAZURE_DEVOPS_ORGZAZURE_DEVOPS_PROJECTZAZURE_DEVOPS_PAT)r   Zorgr  patr  z(https://testcasegenerator.eatanceapp.comZWEBSITE_URLrj   rk   )r  Zwebsite_url
jwt_secretZEMAIL_SMTP_SERVERZEMAIL_SMTP_PORTZ587ZEMAIL_USERNAMEZEMAIL_PASSWORDZEMAIL_FROM_ADDRESSZEMAIL_USE_TLSrY   ZEMAIL_USE_SSLr,  ZEMAIL_RECIPIENTS,)Zsmtp_serverZ	smtp_portusernamer  Zfrom_addressZuse_tlsZuse_sslZ
recipients)r[  ri  r}  r  appr;   T)r8   configr   zError in config API: Frr  r   N)rw   environr?   r   rA   r   r+   r   r  rE   rF   rG   rC   )r  rO   rR   rR   rS   get_config_api&  sL     $$

r  z/api/auth/dashboardc                  C   s  zdt jd} | r| ds2tddddfW S | dd }t }||}|r^|d	srtdd
ddfW S |d d }||}|	|}|| }t
 }g }	|D ]*}
|
d}||kr|| |	|
 q|	}t|}t j}t j}d}d}|rJ|D ]}
|
d}|rzHt|tr<t|dd}n|}|j|kr`|j|kr`|d7 }W nN tk
r } z.td|
d dt|  W Y qW 5 d}~X Y nX qzVt|dd d}|dr
|d }t|trt|dd}n|}|d}W n< tk
rH } ztdt|  d}W 5 d}~X Y nX |||d}td||dW S  tk
r } z2tjdt| dd  tdd!dd"f W Y S d}~X Y nX dS )#zGet user dashboard datar4   r5   FAuthorization token requiredr4  r=  r6   r7   r8   Invalid or expired tokenr9   r:   r   r   ZNeverr   rG  rH  z#Failed to parse date for test case ru   Nc                 S   s   |  dtjS )Nr   )r?   r+   minr   rR   rR   rS   r     r   zdashboard_api.<locals>.<lambda>r   z	%B %d, %Yz&Failed to determine latest test case: r   )totalZ
this_monthlast_generatedT)r8   rI  statszError in dashboard API: rn  z)An error occurred while loading dashboardr   )r   r>   r?   r@   r   rA   r)   rB   rP  Zget_legacy_user_test_casesra  r  r   rY  r+   r   monthyearr[  rC   rJ  rK  rE   rF   r   rT  r   rG   )rJ   rK   rL   r  r+  rI  Zlegacy_test_casesr0  seen_idsZunique_test_casesr  Ztc_idZtotal_countZcurrent_monthZcurrent_yearZthis_month_countr  r   Zparsed_daterO   latestZ	last_dater  rR   rR   rS   dashboard_apiY  s|    







  
r  /api/auth/generate-scriptc            D      C   s
  
z<t jd} | r| ds2tddddfW S | dd }t }||}|r^|d	srtdd
ddfW S |d }t jddpi }|d}|stddddfW S |	|}|stddddfW S |dpi }|dp|d}	|dpg }
|dp|d}t
|tr6ddd |D }nt|p@d}|s^tddddfW S |dp|dp|dp|d}d}d}d}g }|rΐztjdd|id d!}|jr| }|d	r|d"d}t|}|szJtjd#d|id d!}|jr6| }|d	r6|d"d}t|}W nx tk
r   zHd$d l}|d%|}|rt|d&}|s|d'|}|r|d$}d(d)d*d+d,d-g}g }|D ]\}|||D ]H}|jr|jd&kr|d&r||d& n||d$ qqt }|D ]8}||kr8|| || t|d.kr qPqz|d/||jpt|d0||j}|r|d&nd} | s|d1||j}!|!r|!dnd} d}"| r|d2||  d3|}#|#s|d4||  d5|}#|#r|#d }"|d6||jp(|d7||j}$|$r:|$d&nd}%|%sh|d8||j}&|&rd|&dnd}%d}'|%r|d2||% d3|}(|(s|d4||% d5|}(|(r|(d }'|d9||j})|)r|)d&nd}*|*s
|d:||j}+|+r|+dnd}*W n" tk
r.   d }  }%}*Y nX zLtd;|t  d<dt  d=dt  d>dt  d?dt  d@d W n tk
r   Y nX W n tk
r   Y nX Y nX W n tk
r   Y nX t! },|,r|,dAkrtddBddCfW S zt
|trt|nd$}-W n tk
r.   d$}-Y nX dD}.|p<dt  d<dpNdt  d>dp`dt  d@dprddEt  d=dpdt  d?dpddF|d d. dG}/|rdH| nd}0|rdIdJ| nd}1|rdK| nd}2dLdM|
pdN dO|	 dP| d|0 dQ|1 dQ|2 dRt"t  d<d dSt"t  d>d dTt"t  d@d dU|-rd|-ndV dW|/ dQ}3d }4zd$dXl#m$}5 d$dYl%m&}6 |6t'j(dZd[d\}7|5d]d^d_|,|7gd`}8|8)da|.dbd|3dbg}4|4rt*|4d"d r|4j+, nd}9W nd tk
r\   d$dcl-m.}: |:|,dd};|;j/j0j1d]da|.dbd|3dbgd^d_de}<|<j2d$ j3j+, }9Y nX |9sxtddfddCfW S dgg}=g }>|r|=dh| di |>dj t  d<r|=dk|  di |>dl t  d>r|=dm|% di |>dn t  d@	r"|=do|* di |>dp t|=dk
rd$d l}?|?4dqd|9}9|>D ]"}@|?j4dr|@ dsd|9|?j5dt}9	qJdQ|=d du|	rdvnd dw  }Az`d=t  k	r|"	r|?4dxdy|?|" dz |9}9d?t  k	r|'	r|?4d{dy|?|' dz |9}9W n tk

r   Y nX |A|9 }9|6|d| ||	|
|||9d}}Btd|Bd~W S  tk

r }C z@tj7dt|C dd t8|Cddi tddddCf W Y S d }C~CX Y nX d S )Nr4   r5   Fr  r4  r=  r6   r7   r8   r  r9   Tr  r   ztest_case_id is requiredr   r   r   r   r   r   rI  rm  c                 S   s(   g | ] }t |tr|d nt|qS )rt  )r[  r   r?   rC   r  rR   rR   rS   r    s     z'api_generate_script.<locals>.<listcomp>r\   zNo test case content availablerw  rx  z*http://localhost:3000/api/get-codegen-filery     )paramsr8  rt  z/http://localhost:5008/api/get-recording-contentr   z&page\.goto\((['\"])\s*([^'\"]+)\s*\1\)rs  zhttps?://[^\s'\"\)]+z#locator\((['\"])\s*([^'\"]+)\s*\1\)zgetByRole\([^\)]*\)z%getByText\((['\"])\s*([^'\"]+)\s*\1\)z\[name=([\'\"][^\]]+[\'\"])\]z'page\.click\((['\"])\s*([^'\"]+)\s*\1\)z-page\.fill\((['\"])\s*([^'\"]+)\s*\1\),?\s*\n   z-page\.fill\((['\"])([^'\"]*user[^'\"]*)\1\s*,z0locator\((['\"])([^'\"]*user[^'\"]*)\1\)\.fill\(z%(#username|\[name=['\"]username['\"])zpage\\.fill\\((['\"])\s*z(\s*\1\s*,\s*(['\"])\\s*([^'\"]*)\\s*\2\)zlocator\\((['\"])\s*z.\s*\1\)\\.fill\\\((['\"])\\s*([^'\"]*)\\s*\2\)z-page\.fill\((['\"])([^'\"]*pass[^'\"]*)\1\s*,z0locator\((['\"])([^'\"]*pass[^'\"]*)\1\)\.fill\(z%(#password|\[name=['\"]password['\"])z7page\.click\((['\"])([^'\"]*(submit|button)[^'\"]*)\1\)z<(button\[[^\]]*type=['\"]submit['\"][^\]]*\]|#login|\.login)zbCodegen extracted | url=%s | user_sel=%s | user_val=%s | pass_sel=%s | pass_val=%s | submit_sel=%susername_selectorusername_valuepassword_selectorpassword_valuesubmit_selectorr_  zOpenAI API key not configuredr   u  You are a senior QA automation engineer. Generate a complete Playwright (@playwright/test) script. If a start URL or preferred selectors are provided, you MUST use them as the primary values. Do not invent URLs or arbitrary selectors when provided ones exist. Output code only. Create one distinct test(…) block PER provided test case. Do not skip or summarize any case. Do not write placeholder text like 'additional test cases'.)r  r  submit)r  r  )	start_url	selectorsr  preferred_selectorszStart URL: z@Preferred selectors (use these first; adjust only if needed):
- z
- z&Full Codegen Recording for reference:
z
Test Case Types: z, r   z	
Source: z

Test Cases to Automate:
rB  z

Hard requirements:
- If Start URL is provided, navigate to EXACTLY that URL for tests that begin at login/start page.
- If any of the following are provided, use them verbatim in the script (do not replace unless empty):
  USERNAME_SELECTOR = z
  PASSWORD_SELECTOR = z
  LOGIN_BUTTON_SELECTOR = zY
Only infer alternatives when the above are empty.

 Coverage requirements:
 - There are Nu&   test cases listed above.
 - Generate a separate test(…) block for EACH listed test case.
 - Keep test titles identical to the listed case titles when present.
 - Do not add comments such as 'Additional test cases…' — fully implement every case.

Structured summary (authoritative JSON):
)
ChatOpenAI)LangChainTracerrZ   r[   )Zproject_namerg  g?i.  )rf  temperature
max_tokensZopenai_api_keyZ	callbackssystem)r<   rt  ra  rc  )rf  messagesr  r  zLLM returned empty scriptz5const { test, expect } = require('@playwright/test');zconst START_URL = 'z';Z	START_URLzconst USERNAME_SELECTOR = 'ZUSERNAME_SELECTORzconst PASSWORD_SELECTOR = 'ZPASSWORD_SELECTORzconst LOGIN_BUTTON_SELECTOR = 'ZLOGIN_BUTTON_SELECTORzN^\s*import\s+\{\s*test,\s*expect\s*\}\s+from\s+['\"]@playwright/test['\"];?\s*z^\s*const\s+z\s*=.*?;\s*$)flagsz&test.beforeEach(async ({ page }) => {
z  await page.goto(START_URL);
z});

z.(fill\(USERNAME_SELECTOR,\s*)['\"][^'\"]*['\"]z\\1'r  z.(fill\(PASSWORD_SELECTOR,\s*)['\"][^'\"]*['\"]r:   )r+  r   r   r   used_codegenrw  script)r8   	script_idz$Error generating automation script: rn  r
  r  zFailed to generate script)9r   r>   r?   r@   r   rA   r)   rB   r  r   r[  r   rg   rC   r  okr  r  rE   r  r  groupfinditer	lastindexr   ra  r  rY  
IGNORECASEescaperF   r   localsr"   reprZlangchain_openair  Z%langchain.callbacks.tracers.langchainr  rw   r  Zinvokegetattrrt  r  ri  rb  ZchatZcompletionscreatechoicesr   sub	MULTILINEZsave_generated_scriptrG   r   )DrJ   rK   r   r  r9   bodyr   Ztest_docr   r   r   Zstructured_casesZ
cases_textrw  Zcodegen_contentr  r  r  respr  Zresp2Zj2r  Z
goto_matchZgeneric_urlZselector_patternsfoundr  mseenr   Zm_userr  Zm_user2r  Z
m_user_valZm_passr  Zm_pass2r  Z
m_pass_valZm_submitr  Z	m_submit2rd  Zprovided_case_countZsys_msgZextracted_summaryZstart_url_blockZpreferred_selectors_blockZcodegen_blockZuser_msgcompZ_LCChatOpenAIZ_LCLangChainTracerZ_tracerZ_llmZscript_codeZ_OpenAIZ_clientZ_respZheader_linesZreplaced_names_rer   r  r  rO   rR   rR   rS   api_generate_script  s   




 





	

	
	&




  
r  z/api/auth/generated-scriptsc               
   C   s<  zt jd} | r| ds0tddddfW S | dd }t }||}|r\|d	sptdd
ddfW S |d d }||}|	|}|| }t
 }g }	|D ]*}
|
d}||kr|| |	|
 q|	}td|dW S  tk
r6 } z2tjdt| dd tddddf W Y S d }~X Y nX d S )Nr4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   r   T)r8   Zscriptsz!Error listing generated scripts: rn  zFailed to fetch scriptsr   )r   r>   r?   r@   r   rA   r)   rB   Zget_user_generated_scriptsZ!get_legacy_user_generated_scriptsra  r  r   rE   rF   rG   rC   )rJ   rK   r   r  r+  r  Zlegacy_scriptsZall_scriptsr  Zunique_scriptsr  r  rO   rR   rR   rS   api_list_generated_scripts  s2    




r  z'/api/auth/generated-scripts/<script_id>c              
   C   s  zt jd}|r|ds0tddddfW S |dd }t }||}|r\|d	sptdd
ddfW S || |d d }|stddddfW S td|dd|dddW S  t	k
r } z2t
jdt| dd tddddf W Y S d }~X Y nX d S )Nr4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   zScript not foundr   Tr  r\   r   )r8   r  r   z Error getting generated script: rn  zFailed to fetch scriptr   )r   r>   r?   r@   r   rA   r)   rB   r   rE   rF   rG   rC   )r  rJ   rK   r   r  r   rO   rR   rR   rS   api_get_generated_script   s(    



r  z/scripts/<script_id>c              
   C   sb   zt d| dW S  tk
r\ } z0tjdt| dd t dddd	f W Y S d }~X Y nX d S )
Nzscript-view.html)r  z"Error rendering script view page: Trn  r   zFailed to load script viewr   r   )r   rE   rF   rG   rC   )r  rO   rR   rR   rS   view_generated_script8  s
    r  z/view-recordingc               
   C   s   zDt jd} | s$tddddfW S dd l}|j| } td| dW S  tk
r } z0tj	d	t
| d
d tddddf W Y S d }~X Y nX d S )Nry  r   No file specifiedr  r   r   zrecording-view.html)r  z%Error rendering recording view page: Trn  zFailed to load recording viewr   r   rH   r?   r   urllib.parseparseunquoterE   rF   rG   rC   )r  urllibrO   rR   rR   rS   view_recordingB  s    r  z/create-from-recordingc               
   C   s   zDt jd} | s$tddddfW S dd l}|j| }td|dW S  tk
r } z0tj	d	t
| d
d tddddf W Y S d }~X Y nX d S )Nry  r   zNo codegen file specifiedr  r   r   zcreate-from-recording.htmlrw  ,Error rendering create-from-recording page: Trn  zFailed to load pager   r  )r  r  rw  rO   rR   rR   rS   create_from_recording_pageR  s    r  c               
   C   s   zHt jdd} ddl}|j| p$d} ddl}|j| }t	d|dW S  t
k
r } z0tjdt| dd	 t	d
dddf W Y S d}~X Y nX dS )zLightweight handoff page that records the attached codegen file in localStorage
    and redirects to the main index with a special mode enabled.
    ry  r\   r   Nzattach-codegen.htmlr  r  Trn  r   z)Failed to start codegen-assisted creationr  r   )r   rH   r?   r  r   r  rw   rx   r   r   rE   rF   rG   rC   )r  r  rw   Zfilename_onlyrO   rR   rR   rS   create_from_recording`  s    r  z/api/list-codegen-filesc               
      s  zZt jdd} d}| drzX| ddd }t }||}|rv|drv|drv|d d	pt|d d
}W n2 tk
r } zt	d|  W 5 d}~X Y nX |st
ddddfW S t }|j}z4ddlm}m} td| d| dt|  W n( tk
r,   td| d Y nX z|d }	dd|id|id|id|igi}
t|	|
ddgd}i }ddlm fd d! |D ]}|d"p|d#p|d$p|d%rtj|d%nd}t|tr|sq|d&sq||d%p$d'|d
 |d(pN|d)pN|d*pNt d+d,}||}|r |d(  |d( kr|||< qt|  fd-d.d/d0dd1 }|D ]H}z* |d(}|  !d2d3}||d(< W n tk
r   Y nX qt
d/|d4W W S  tk
rX } z,t"d5|  t
dd6dd7f W Y W S d}~X Y nX W nR tk
r } z2tj"d8t| d/d9 t
dd:dd7f W Y S d}~X Y nX dS );zReturn recent codegen recordings for the authenticated user, aligned with desktop logic.

    Response shape:
      { success: true, files: [ { name, path, date, source } ] }
    r4   r\   Nr5   r6   r7   r8   r9   r:   r   z/JWT verification failed in list-codegen-files: FZUnauthorizedr4  r=  r   )r  r  zlist-codegen-files: user_id=z, mongo_db=z, mongo_uri_set=z, mongo_config_log_failedcodegen_recordings$oruserIdcurrentJWTUserIdr+  owner_iddater  )r   r  rN  timezonec                    s   zxt | tr4| jdkr&| j jdW S |  jW S t | trvt| dd}|jdkrh|j jd}| jW S W n tk
r   Y nX t	 jS )z>Normalize to timezone-aware UTC datetime for safe comparisons.N)tzinforG  rH  )
r[  r+   r  rK  utc
astimezonerC   rJ  rE   r   )r  dtr  rR   rS   _to_dt  s    



z&list_codegen_files_api.<locals>._to_dtr  original_filenamer   rx   .spec.js
mongodb://r  r   Z	createdAtr   )r   rx   r  sourcec                    s    | d S )Nr  rR   r   )r  rR   rS   r     r   z(list_codegen_files_api.<locals>.<lambda>Tr   rl   rH  rG  )r8   r   z*Mongo query failed in list-codegen-files: zFailed to load recordingsr   z!Error in list-codegen-files API: rn  zServer error)#r   r>   r?   r@   rA   r)   rB   rE   rF   r   r   r  r  r  r  r   r  r   r   r   r   r+   r  rw   rx   r   r[  rC   r   r   sortedr  r  rK  rG   )rJ   r+  rK   r   r  rO   r  r  r  colZ
user_queryZdocsZitems_by_namer   fnamer  existingr  itZdt_normZisorR   )r  r  rS   list_codegen_files_apir  s    

 "$
 *
 "
.r  z/api/get-recording-contentc               
   C   s  zt jd} | s(tddddfW S dd l}dd l}|j| }t|t	r(|
dr(zT|dd }t }|j}t|d	r|d
 d||in|d
 d|i}W n tk
r   d }Y nX |r(dD ]R}||}	t|	t	r|	rtd|	|dp|dpd| dd  W S q|dkrzt }|j}|d
 ji dgd}
|
rdD ]V}|
|}	t|	t	r^|	r^|
dp|
dpd}td|	|d  W W S q^W n tk
r   Y nX |j|}zdt }|j}dd }d }z0|d
 dd|id|id|igi}||}W n tk
rB   d }Y nX |sz0|d dd|id|id|igi}||}W n tk
r   d }Y nX |r@|jddd}|j|dd |j||}z(t|d d!d"}|| W 5 Q R X W n: tk
r* } ztd#| d$|  W 5 d }~X Y nX td||dW W S W n4 tk
rv } ztd%|  W 5 d }~X Y nX zddd l}|jd&| d'd(}|jd)kr| }|d*r|d+rtd|d+ |dW W S W n8 tk
r } ztd,t	|  W 5 d }~X Y nX zb|jddd|}|j|rvt|d-d!d"}|  }W 5 Q R X td||j|dW W S W n8 tk
r } ztd.t	|  W 5 d }~X Y nX tdd/dd0fW S  tk
r } z2tj!d1t	| dd2 tdd3dd4f W Y S d }~X Y nX d S )5Nry  Fr  r4  r   r   r  r\   r3   r  r   rt  Zfile_contentr  Zscript_contentcoder  Tr  r   z
recording-r  )r8   rt  r  z[object Object]r  r  zrecording.spec.jsc                 S   s6   | sd S dD ]$}|  |}t|tr|r|  S qd S )Nr   )r?   r[  rC   )r   r   valrR   rR   rS   _extract_content  s    

z/get_recording_content.<locals>._extract_contentr	  r  Zgenerated_scriptsr   r   Zexportsr<  r>  r?  r@  zCould not write cache file ru   z&MongoDB rehydrate by filename failed: z0http://localhost:3000/api/get-codegen-file?file=r  r~  r   r8   rt  z"Could not fetch from desktop app: r  zCould not read file directly: z Could not load recording contentr   z!Error getting recording content: rn  z!Failed to fetch recording contentr   )"r   rH   r?   r   r  rw   r   r  r[  rC   r@   rK  r  r)   r  r   r   r3   rE   rx   r   rg   rU  rV  rW  rF   r   r   r  r  r  r{   r   rG   )r  r  rw   rawZmongo_idr   r  r   r   r"  r  fnr  r#  rt  ZrecgZ	cache_dir
cache_pathrQ   r   rO   r  Zdesktop_responser  r   rR   rR   rS   get_recording_content  s    8

8

 	

("& &r(  z!/api/diagnostics-recordings-countc            
   
   C   sx  zt jdd} d}| drzX| ddd }t }||}|rv|drv|drv|d d	pt|d d
}W n2 tk
r } zt	d|  W 5 d}~X Y nX t }|j
}|d }|i }d}	|r|dd|id|id|id|igi}	tdt|t|	|rt|nddW S  tk
rr } z2tjdt| dd tddddf W Y S d}~X Y nX dS )zFReturn diagnostics: total recordings and count for current user (web).r4   r\   Nr5   r6   r7   r8   r9   r:   r   z9JWT verification failed in diagnostics-recordings-count: r  r   r	  r
  r  r+  r  T)r8   r  ZforUserr
  z'Error in diagnostics-recordings-count: rn  FzDiagnostics failedr4  r   )r   r>   r?   r@   rA   r)   rB   rE   rF   r   r  count_documentsr   rB  rC   rG   )
rJ   r+  rK   r   r  rO   r  r  r  Zfor_userrR   rR   rS   diagnostics_recordings_counte  s<    

 "
	*r*  /api/auth/reset-passwordc            	   
   C   s  zdt j} | s"tddddfW S | dd }|r>d|krRtddddfW S t }|jd|i}|s|td	d
dW S ||}|d st	
d| d|dd  td	d
dW S zLddlm} |||d |d d}|rt	d|  nt	
d|  W n> tk
rF } zt	
d| dt|  W 5 d}~X Y nX t	d|  td	ddW S  tk
r } zPt	
dt|  t|d| r| ddndd tddddf W Y S d}~X Y nX dS ) zHandle password reset requestFr3  r4  r   r;   r\   r  r  TzJIf an account with that email exists, a password reset link has been sent.r8   z!Failed to create reset token for ru   r   Unknown errorr   )send_password_reset_emailrK   
expires_at)r;   Zreset_tokenr.  z+Password reset email sent successfully to: z(Failed to send password reset email to: z&Error sending password reset email to Nz$Password reset requested for email: zcIf an account with that email exists, a password reset link has been sent. Please check your email.zError in reset password API: r+  )r
  r;   'An error occurred during password resetr   )r   r  r   r?   r  r)   r  r   Zcreate_password_reset_tokenrF   rG   r  r-  r   rE   rC   r   )	r  r;   rL   r9   r   r-  Z
email_sentZemail_errorrO   rR   rR   rS   reset_password_api  sT    


,
"r0   /api/auth/reset-password-confirmc               
   C   s  zFt j} | s"tddddfW S | dd }| dd }| dd }|sjtdd	ddfW S |stdd
ddfW S t|dk rtddddfW S ||krtddddfW S t }|||}|d rt	d|dd  d tdddW S t
d|dd  d|dd  td|ddddfW S W nx tk
r } zXtdt|  t|d| r| dddd ndd tddddf W Y S d}~X Y nX dS )z"Handle password reset confirmationFr3  r4  r   rK   r\   new_passwordconfirm_passwordzReset token is requiredzNew password is required   z+Password must be at least 6 characters longzPasswords do not matchr8   z1Password reset successfully completed for token: Nr   rm   TzHPassword reset successfully. You can now sign in with your new password.z!Password reset failed for token: z... - r   r,  zFailed to reset passwordz%Error in reset password confirm API: r1  )r
  rK   r/  r   )r   r  r   r?   r  rY  r)   Zuse_password_reset_tokenrF   r   r   rE   rG   rC   r   )r  rK   r2  r3  rL   r  rO   rR   rR   rS   reset_password_confirm_api  sD    

&

*r5  z/api/auth/system-overviewc               
   C   s  zt jd} | r| ds0tddddfW S | dd }t }||}|r\|d	sptdd
ddfW S |d d }||}|d	 rt|W S td|d ddfW S W nN t	k
r  } z.t
dt|  tddddf W Y S d}~X Y nX dS )z Get system overview (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   r   rE  zError in system overview API: z/An error occurred while loading system overviewr   N)r   r>   r?   r@   r   rA   r)   rB   Zget_system_overviewrE   rF   rG   rC   )rJ   rK   rL   r  r+  Zsystem_overviewrO   rR   rR   rS   system_overview_api  s"    


r6  z/api/auth/recent-usersc               
   C   s(  zt jd} | r| ds0tddddfW S | dd }t }||}|r\|d	sptdd
ddfW S |d d }||}|d	 rd|kr|d dd ng }td|dW S td|d ddfW S W nN t	k
r" } z.t
dt|  tddddf W Y S d}~X Y nX dS )zGet recent users (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   usersNr   T)r8   r7  r   rE  zError in recent users API: z,An error occurred while loading recent usersr   )r   r>   r?   r@   r   rA   r)   rB   Zget_all_usersrE   rF   rG   rC   )rJ   rK   rL   r  r+  r7  Zrecent_usersrO   rR   rR   rS   recent_users_api  s*    


r8  z/api/auth/all-usersc            	   
   C   s.  zt jd} | r| ds0tddddfW S | dd }t }||}|r\|d	sptdd
ddfW S |d d }tt j	dd}tt j	dd}|
|||}|d	 rt|W S td|d ddfW S W nN tk
r( } z.tdt|  tddddf W Y S d}~X Y nX dS )z*Get all users with pagination (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   pageper_pager   r   rE  zError in all users API: z%An error occurred while loading usersr   N)r   r>   r?   r@   r   rA   r)   rB   rB  rH   Zget_all_users_paginatedrE   rF   rG   rC   )	rJ   rK   rL   r  r+  r9  r:  r7  rO   rR   rR   rS   all_users_apiB  s&    

r;  z/api/auth/system-healthc               
   C   s  zt jd} | r| ds0tddddfW S | dd }t }||}|r\|d	sptdd
ddfW S |d d }||}|d	 rt|W S td|d ddfW S W nN t	k
r  } z.t
dt|  tddddf W Y S d}~X Y nX dS )z%Get system health status (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   r   rE  zError in system health API: z.An error occurred while checking system healthr   N)r   r>   r?   r@   r   rA   r)   rB   Zget_system_healthrE   rF   rG   rC   )rJ   rK   rL   r  r+  ZhealthrO   rR   rR   rS   system_health_apif  s"    


r<  z/api/auth/user-analyticsc               
   C   s  zt jd} | r| ds0tddddfW S | dd }t }||}|r\|d	sptdd
ddfW S |d d }||}|d	 rt|W S td|d ddfW S W nN t	k
r  } z.t
dt|  tddddf W Y S d}~X Y nX dS )z(Get detailed user analytics (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   r   rE  zError in user analytics API: z.An error occurred while loading user analyticsr   N)r   r>   r?   r@   r   rA   r)   rB   Zget_detailed_user_analyticsrE   rF   rG   rC   )rJ   rK   rL   r  r+  Z	analyticsrO   rR   rR   rS   user_analytics_api  s"    


r=  z/api/auth/create-userc               
   C   s(  zt jd} | r| ds0tddddfW S | dd }t }||}|r\|d	sptdd
ddfW S |d d }t  }|stddddfW S |	||}|d	 rt|W S td|d ddfW S W nN t
k
r" } z.tdt|  tddddf W Y S d}~X Y nX dS )zCreate a new user (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   r3  r   r   zError in create user API: z%An error occurred while creating userr   N)r   r>   r?   r@   r   rA   r)   rB   r  Zcreate_user_by_adminrE   rF   rG   rC   rJ   rK   rL   r  r+  r  r  rO   rR   rR   rS   create_user_api  s(    

r?  z/api/auth/export-datac            
   
   C   sL  zt jd} | r| ds0tddddfW S | dd }t }||}|r\|d	sptdd
ddfW S |d d }||}|d	 rddl	m
} ddlm} |j|d dd}||dddt d didW S td|d ddfW S W nN tk
rF }	 z.tdt|	  tddddf W Y S d}	~	X Y nX dS )zExport system data (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   r   r  )	json_utilr  rs  )indentzapplication/jsonr  z#attachment; filename=system-export-z%Y%m%dz.jsonr  r   rE  zError in export data API: z&An error occurred while exporting datar   N)r   r>   r?   r@   r   rA   r)   rB   Zexport_system_datar   r  Zbsonr@  dumpsr+   r   r   rE   rF   rG   rC   )
rJ   rK   rL   r  r+  Zexport_resultr  r@  r  rO   rR   rR   rS   export_data_api  s4    

 rC  z/api/auth/system-logsc               
   C   s  zt jd} | r| ds0tddddfW S | dd }t }||}|r\|d	sptdd
ddfW S |d d }||}|d	 rt|W S td|d ddfW S W nN t	k
r  } z.t
dt|  tddddf W Y S d}~X Y nX dS )zGet system logs (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   r   rE  zError in system logs API: z+An error occurred while loading system logsr   N)r   r>   r?   r@   r   rA   r)   rB   Zget_system_logsrE   rF   rG   rC   )rJ   rK   rL   r  r+  logsrO   rR   rR   rS   system_logs_api  s"    


rE  z/api/auth/backup-systemc               
   C   s  zt jd} | r| ds0tddddfW S | dd }t }||}|r\|d	sptdd
ddfW S |d d }||}|d	 rt|W S td|d ddfW S W nN t	k
r  } z.t
dt|  tddddf W Y S d}~X Y nX dS )z!Create system backup (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   r   rE  zError in backup system API: z'An error occurred while creating backupr   N)r   r>   r?   r@   r   rA   r)   rB   Zcreate_system_backuprE   rF   rG   rC   )rJ   rK   rL   r  r+  Zbackup_resultrO   rR   rR   rS   backup_system_api  s"    


rF  z/api/auth/system-settingsc               
   C   s(  zt jd} | r| ds0tddddfW S | dd }t }||}|r\|d	sptdd
ddfW S |d d }t  }|stddddfW S |	||}|d	 rt|W S td|d ddfW S W nN t
k
r" } z.tdt|  tddddf W Y S d}~X Y nX dS )z#Update system settings (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   r3  r   r   zError in system settings API: z)An error occurred while updating settingsr   N)r   r>   r?   r@   r   rA   r)   rB   r  Zupdate_system_settingsrE   rF   rG   rC   r>  rR   rR   rS   system_settings_api5  s(    

rG  z /api/auth/user-details/<user_id>c              
   C   s  zt jd}|r|ds0tddddfW S |dd }t }||}|r\|d	sptdd
ddfW S |d d }||| }|d	 rt|W S td|d ddfW S W nN t	k
r } z.t
dt|  tddddf W Y S d}~X Y nX dS )zGet user details (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   r   rE  zError in user details API: z,An error occurred while loading user detailsr   N)r   r>   r?   r@   r   rA   r)   rB   Zget_user_detailsrE   rF   rG   rC   )r+  rJ   rK   rL   r  admin_user_idr  rO   rR   rR   rS   user_details_apiZ  s"    

rI  z/api/auth/update-user/<user_id>PUTc           	   
   C   s*  zt jd}|r|ds0tddddfW S |dd }t }||}|r\|d	sptdd
ddfW S |d d }t  }|stddddfW S |	|| |}|d	 rt|W S td|d ddfW S W nN t
k
r$ } z.tdt|  tddddf W Y S d}~X Y nX dS )zUpdate user (admin only)r4   r5   Fr  r4  r=  r6   r7   r8   r  r9   r:   r3  r   r   zError in update user API: z%An error occurred while updating userr   N)r   r>   r?   r@   r   rA   r)   rB   r  Zupdate_user_by_adminrE   rF   rG   rC   )	r+  rJ   rK   rL   r  rH  r  r  rO   rR   rR   rS   update_user_apiz  s(    

rK  z/api/execution/startc               
   C   s   z~t  } | s"tddddfW S | d}| d}| d}|sXtddddfW S t }|j|||d	}td
|ddW S  tk
r } z2tdt	|  tdt	|ddf W Y S d}~X Y nX dS )zStart a new test executionFr3  rr  r   r   r
  Z	sessionIdztestCaseId is required)r   r+  r&  TzTest execution started)r8   r   r   zError starting test execution: r   N)
r   r  r   r?   r)   Zcreate_test_executionrE   rF   rG   rC   )r  r   r+  r&  rL   r   rO   rR   rR   rS   start_execution  s.    



rL  z$/api/execution/update/<execution_id>c           
   
   C   s  zt  }|s"tddddfW S |d}|d}|d}|d}t }|j| ||||d	}|r|r|d
kr|d}|r|j||d tdddW S tddddfW S W nR tk
r }	 z2t	dt
|	  tdt
|	ddf W Y S d}	~	X Y nX dS )z!Update an existing test executionFr3  rr  r   r  r  rD  Z
detailsUrl)r   r  r  rD  details_url)passedfailedrC  r   )r   r  TzExecution updated successfullyr4  zFailed to update executionzError updating test execution: r   N)r   r  r   r?   r)   Zupdate_test_executionZ update_test_case_execution_statsrE   rF   rG   rC   )
r   r  r  r  rD  rM  rL   r8   r   rO   rR   rR   rS   update_execution  s@    





rP  z/api/execution/historyc               
   C   s   zt jd} t jd}d}t|dkr0|}nt|dkrD|d }tt jdd}tt jdd}t }|j| |||d	}td
|t|dW S  t	k
r } z2t
dt|  tdt|ddf W Y S d}~X Y nX dS )z+Get execution history with optional filtersr
  r   Nr7   r   r   2   offset)r+  r   r   rR  T)r8   r   countz$Error retrieving execution history: Frr  r   )r   rH   r?   r"  rY  rB  r)   r   r   rE   rF   rG   rC   )r+  Ztest_case_idsr   r   rR  rL   r   rO   rR   rR   rS   r     s2    
r   z/api/execution/<execution_id>c              
   C   s   z<t  }|| }|r&td|dW S tddddfW S W nP tk
r } z2tdt|  tdt|ddf W Y S d	}~X Y nX d	S )
zGet a specific execution by IDT)r8   r   FzExecution not foundrr  r   zError retrieving execution: r   N)r)   r   r   rE   rF   rG   rC   r   rL   r   rO   rR   rR   rS   r     s    

r   z/execution/<execution_id>c              
   C   s   zDt  }|| }|r6d|kr&i |d< d|kr6g |d< td|| dW S  tk
r } z.tdt|  tdd| ddf W Y S d}~X Y nX dS )zRender a full-page view for a specific execution's details.
    If the execution isn't found, still render the page shell and let the client fetch.
    r  rD  execution-details.htmlr   r   z(Error rendering execution details page: Nr   )r)   r   r   rE   rF   rG   rC   rT  rR   rR   rS   view_execution_details_page  s    
rW  
/executionc               
   C   s   t jdpt jd} | s,tddddfS zDt }|| }|rbd|krRi |d< d|krbg |d< td	|| d
W S  tk
r } z.tdt	|  td	d| d
df W Y S d}~X Y nX dS )zASupport /execution?id=<execution_id> and render details directly.r:   r   r   zExecution ID is requiredr   r   r  rD  rU  rV  z-Error rendering execution details via query: Nr   )
r   rH   r?   r   r)   r   rE   rF   rG   rC   rT  rR   rR   rS   !view_execution_details_page_query4  s    
rY  z#/api/execution/check/<test_case_id>c              
   C   s   z>t  }|j| dd}t|dk}td||r4t|nddW S  tk
rz } ztdt|ddf W Y S d	}~X Y nX d	S )
z*Check if a test case has execution historyr7   r   r   T)r8   has_executionsZexecution_countFrr  r   N)r)   r   rY  r   rE   rC   )r   r   r   rZ  rO   rR   rR   rS   check_execution_historyG  s     
r[  z/api/execution/statsc            
   
   C   s  zt jd} t jd}t }i }| r0| |d< |r<||d< |j|}|j|ddi}|j|ddi}|j|ddi}|dkr|| d	 nd}td
||||t|dddW S  tk
r }	 z2t	
dt|	  tdt|	ddf W Y S d}	~	X Y nX dS )zGet execution statisticsr
  r   r+  r  rN  rO  runningr   rN  Trs  )r  rN  rO  r\  success_rate)r8   r  z"Error retrieving execution stats: Frr  r   N)r   rH   r?   r)   Ztest_executions_collectionr)  r   roundrE   rF   rG   rC   )
r+  r   rL   queryZtotal_executionsZpassed_executionsZfailed_executionsZrunning_executionsr]  rO   rR   rR   rS   get_execution_stats\  s4    
r`  r   c              
   C   s*  t dtj  tjdr.tddidfS ztjdrd}dd	 tjd
D }t|dkrv|d dkrv|d }|ptj	
dptj	
d}|rt }||}|rd|kri |d< |rd|krg |d< td||ddfW S W n4 tk
r } zt d|  W 5 d}~X Y nX tddddfS )zHandle 404 Not Found errorsz404 error: /api/rG   zAPI endpoint not foundr   rX  Nc                 S   s   g | ]}|r|qS rR   rR   )r^   prR   rR   rS   r    s      z#not_found_error.<locals>.<listcomp>r   rs  r   r   r7   r:   r   r  rD  rU  rV  r   z!Error in 404 execution fallback: r   zNThe page you're looking for doesn't exist. Please check the URL and try again.r   )rF   r   r   r   rx   r@   r   rA   rY  rH   r?   r)   r   r   rE   rG   )rG   Zexec_idpartsrL   r   r   rR   rR   rS   not_found_error  s*    
"rd  r   c                 C   s@   t dt|   tjdr0tddidfS tddddfS )	z!Handle 500 Internal Server errorsz500 error: ra  rG   zInternal server error occurredr   r   z8Something went wrong on our end. Please try again later.r   )rF   rG   rC   r   rx   r@   r   r   r   rR   rR   rS   internal_error  s    re  z	/__routesc               
   C   s   zdg } t j D ]6}dtdd |jD }| t||j|d qt| dd d} t	d| iW S  t
k
r } zt	d	t|id
f W Y S d }~X Y nX d S )Nr  c                 S   s   g | ]}|d kr|qS ))HEADZOPTIONSrR   )r^   r  rR   rR   rS   r    s      z!__list_routes.<locals>.<listcomp>)ruler
  r  c                 S   s   | d S )Nrg  rR   )r  rR   rR   rS   r     r   z__list_routes.<locals>.<lambda>r  routesrG   r   )r  Zurl_mapZ
iter_rulesrg   r  r  r   rC   r
  r   rE   )rh  rg  r  rO   rR   rR   rS   __list_routes  s    
ri  rE  c                 C   s>   t dtj  tjdr.tddidfS tddddfS )	zHandle 403 Forbidden errorsz403 error: ra  rG   zAccess forbiddenrE  r   z2You don't have permission to access this resource.r   rF   r   r   r   rx   r@   r   r   r   rR   rR   rS   forbidden_error  s    rk  r   c                 C   s>   t dtj  tjdr.tddidfS tddddfS )	zHandle 400 Bad Request errorsz400 error: ra  rG   zBad requestr   r   z?The request was invalid. Please check your input and try again.r   rj  r   rR   rR   rS   bad_request_error  s    rl  c                 C   sZ   z@d| j krd| j d< d| j kr*d| j d< d| j kr>d| j d< W n tk
rT   Y nX | S )Nr  r$  r  r  r  r  )r>   rE   )r  rR   rR   rS   add_global_no_cache_headers  s    




rm  __main__z0.0.0.0i  )hostport)rr   )rS  r   r   r   r   r   Zconfig.config_loaderr   r   r	   r
   r   r   r   r   r   Zcurrent_configZwebsite_configZdatabase_configZ	ai_configZintegrations_configZemail_configZsecurity_configZlogging_configrP  r?   ImportErrorrO   rE   r   r   r   r   r   r   r   r   r   r   Z
flask_corsr   rx  r   r  r    Zai.generatorr!   r"   r  r$   r  r%   r&   r'   r(   Zutils.mongo_handlerr)   rw   r  r+   r,   r(  r  loggingbasicConfigINFO	getLogger__name__rF   r  r  r/   r   r0   	functoolsr2   r  Zbson.objectidr3   rv   rV   rX   r  r  r   r   ri   r  r  Zsession_secretr   r   r   Zrouter   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  ra  rQ  r  r  r  r  r  r  r	  r  rL   r  r#  r&  r*  r2  r7  r;  rC  rL  rQ  rU  rV  rW  rY  r]  rk  rl  rm  r}  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r(  r*  r0  r5  r6  r8  r;  r<  r=  r?  rC  rE  rF  rG  rI  rK  rL  rP  r   r   rW  rY  r[  r`  Zerrorhandlerrd  re  ri  rk  rl  Zafter_requestrm  runrR   rR   rR   rS   <module>   st  ,,
#


"




#




P
X



"


(
       N
 >
7
4
X
X
 
H
|
t
x

 Z
-
,
:
=
*
5
&
,
^
&
N

0
$

%
:
I
(
%
"
+
#
"
,
"

2
b  D 	wz%A/$#$)$%* 


&

	


