o
    h;                     @   s  d Z ddlZddlZddlmZ ddlmZ ddlmZm	Z	m
Z
 ddlmZ ddlZddlmZmZ ddlZddlZddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZmZm Z  ddl!m"Z" ddl#Z$ddl%m&Z& eG dd dZ'eG dd dZ(eG dd dZ)G dd dZ*G dd dZ+G dd dZ,G dd dZ-G dd dZ.G d d! d!Z/d"d# Z0d$d% Z1e2d&kre1  dS dS )'zv
TAS License Checker
================================================================================================
    N)Path)	dataclass)ListDictOptional)datetime)ThreadPoolExecutoras_completed	webdriverOptionsByWebDriverWaitexpected_conditions)TimeoutExceptionWebDriverExceptionNoSuchElementException)fuzz)parserc                   @   s~   e Zd ZU dZdZeed< dZeed< dZ	eed< dZ
eed	< d
Zeed< dZeed< dZeed< dZeed< dZeed< dS )SimpleConfigzSimple configurationIhttps://occupationallicensing.justice.tas.gov.au/Search/onlinesearch.aspxwebsite_urlU   name_similarity_required   max_retry_attempts   request_timeout_seconds      ?delay_between_requests   parallel_browsersT	test_modetest_record_limitshow_browser_for_captchaN)__name__
__module____qualname____doc__r   str__annotations__r   intr   r!   r#   floatr%   r&   boolr'   r(    r2   r2   $/var/www/html/captchaScrapper/tas.pyr   #   s   
 r   c                   @   sT   e Zd ZU dZeed< eed< eed< eed< dZeed< dd	 Zd
e	fddZ
dS )EmployeeRecordz)Holds one employee's information from CSVpayroll_numberemployee_namelicense_number
csv_expiryr   csv_row_numberc                 C   sD   t | j | _t | j | _t | j | _t | j | _dS )z)Remove extra spaces and clean up the dataN)r-   r5   stripr6   r7   r8   selfr2   r2   r3   
clean_dataN   s   zEmployeeRecord.clean_datareturnc                 C   s   t | jo| jS )z9Check if this record has the minimum required information)r1   r7   r6   r;   r2   r2   r3   has_required_dataU   s   z EmployeeRecord.has_required_dataN)r)   r*   r+   r,   r-   r.   r9   r/   r=   r1   r?   r2   r2   r2   r3   r4   E   s   
 r4   c                   @   s   e Zd ZU dZdZeed< dZeed< dZeed< dZ	eed< dZ
eed< d	Zeed
< dZeed< dZeed< dZeed< defddZdS )SearchResultz)Holds the result of searching TAS website	Not Found
found_namelicense_typelicense_expiry
No Licensename_matchesexpiry_status error_messager   how_many_retriesg        search_time_secondsF
was_cachedr>   c                 C   s   | j dko| j S )z-Did we successfully find license information?rA   )rB   rI   r;   r2   r2   r3   is_successfulg   s   zSearchResult.is_successfulN)r)   r*   r+   r,   rB   r-   r.   rC   rD   rF   rG   rI   rJ   r/   rK   r0   rL   r1   rM   r2   r2   r2   r3   r@   Z   s   
 r@   c                   @   s^   e Zd ZdZdefddZdd Zdejfdd	Z	d
d Z
dd Zdd Zdd Zdd ZdS )OptimizedBrowserManagerzAManages Chrome browser for reliable scraping with CAPTCHA supportconfigc                 C   s,   || _ d | _d | _d| _t | _d| _d S )NF)rO   browserwait_helpersetup_complete	threadingLocklockcaptcha_handled)r<   rO   r2   r2   r3   __init__s   s   

z OptimizedBrowserManager.__init__c                 C   s   | j rdS | j2 | j r	 W d   dS td |  | _t| j| jj| _| 	  d| _ td W d   dS 1 s=w   Y  dS )z$Create Chrome browser for processingNz5Setting up Chrome browser for TAS license checking...Tz)Browser ready for TAS license processing!)
rR   rU   print_create_chrome_browserrP   r   rO   r!   rQ   _initialize_search_pager;   r2   r2   r3   setup_browsers{   s   

"z&OptimizedBrowserManager.setup_browsersr>   c                 C   s   t  }| jjs|d |d |d |d |d |d |d |d |d	d
g |dd tj|d}|d |S )z+Create Chrome browser with optimal settings
--headless--no-sandbox--disable-dev-shm-usagez--disable-gpuz--disable-extensionsz--disable-loggingz--window-size=1280,720z---disable-blink-features=AutomationControlledexcludeSwitcheszenable-automationuseAutomationExtensionFoptionszEObject.defineProperty(navigator, 'webdriver', {get: () => undefined}))r   rO   r(   add_argumentadd_experimental_optionr   Chromeexecute_script)r<   chrome_optionsdriverr2   r2   r3   rY      s   








z.OptimizedBrowserManager._create_chrome_browserc              
   C   s   z/| j | jj | jttj	df}|
  | jttj	df}|
  td W dS  tyC } ztd|   d}~ww )z5Initialize the TAS search page with required settingsn//*[@id="ctl00_ctl00_ctl00_ctlMainContent_ctlMainContent_MainContent_ctlOnlineSearch_rblLicenceTypeOptions_3"]v//*[@id="ctl00_ctl00_ctl00_ctlMainContent_ctlMainContent_MainContent_ctlOnlineSearch_rblLicenceTypeCategoryOptions_1"]u,   ✓ TAS search page initialized successfullyz-ERROR: Failed to initialize TAS search page: N)rP   getrO   r   rQ   untilECelement_to_be_clickabler   XPATHclickrX   	Exception)r<   radio_option_3radio_category_1er2   r2   r3   rZ      s(   

z/OptimizedBrowserManager._initialize_search_pagec                 C   s   | j s|   | j| jfS )z@Get the browser instance (single browser for TAS due to CAPTCHA))rR   r[   rP   rQ   r;   r2   r2   r3   get_browser   s   z#OptimizedBrowserManager.get_browserc                 C   s   dS )z0Return browser - no-op for single browser systemNr2   )r<   rP   r2   r2   r3   return_browser   s   z&OptimizedBrowserManager.return_browserc                 C   s   | j rdS z:t| jddd }|r=td td td td td	 td
 td td d| _ td W dS W dS  tyI   Y dS w )zHandle CAPTCHA if it appearsN   c                 S   s   t dd | tjdD S )Nc                 s   s    | ]}|  V  qd S N)is_displayed).0iframer2   r2   r3   	<genexpr>   s    zUOptimizedBrowserManager.handle_captcha_if_needed.<locals>.<lambda>.<locals>.<genexpr>z%//iframe[contains(@src, "recaptcha")])anyfind_elementsr   ro   )dr2   r2   r3   <lambda>   s    zBOptimizedBrowserManager.handle_captcha_if_needed.<locals>.<lambda>=
============================================================u   ⚠️  CAPTCHA DETECTED!<============================================================z*A CAPTCHA has appeared on the TAS website.z/Please solve the CAPTCHA in the browser window,z/then press ENTER here to continue processing...z#Press ENTER after solving CAPTCHA: Tu-   ✓ CAPTCHA handled, continuing processing...)rV   r   rP   rl   rX   inputr   )r<   captcha_iframer2   r2   r3   handle_captcha_if_needed   s*   z0OptimizedBrowserManager.handle_captcha_if_neededc                 C   s0   | j rz| j   W dS    td Y dS dS )zClose browser when program endsz)WARNING: Browser failed to close properlyN)rP   quitrX   r;   r2   r2   r3   cleanup_all_browsers   s   z,OptimizedBrowserManager.cleanup_all_browsersN)r)   r*   r+   r,   r   rW   r[   r   re   rY   rZ   ru   rv   r   r   r2   r2   r2   r3   rN   p   s    rN   c                   @   s   e Zd ZdZdedefddZdedefdd	Zdedefd
dZ	dededefddZ
dededefddZdedefddZdedefddZdejdededefddZdejdefddZdejdedefd d!Zd"S )#SeleniumLicenseSearcherz.Searches TAS government website using SeleniumrO   browser_managerc                 C   s&   || _ || _i | _t | _i | _d S rx   )rO   r   search_cacherS   rT   
cache_lock
name_cache)r<   rO   r   r2   r2   r3   rW      s
   

z SeleniumLicenseSearcher.__init__namer>   c                 C   s~   |sdS || j v r| j | S | |}|   }t|dkr2|d  dd|dd  }n|  }|| j |< |S )zEConvert name to standard format for comparison with enhanced cleaningrH   r   ,  N)r   _clean_name_for_matchingr:   uppersplitlenjoin)r<   r   cleaned_nameparts
normalizedr2   r2   r3   normalize_employee_name   s   


"
z/SeleniumLicenseSearcher.normalize_employee_namec                 C   s   |sdS t | }d| }|  }g }|D ] }t|dkr*t|dkr*q|dr6t|dkr6q|| qg }|D ]}d|v rQ|d}|| q@|| q@dd |D }|red|S |S )	z>Clean name by removing common variations and formatting issuesrH   r   r$   .rw   -c                 S   s   g | ]}|  r|qS r2   )r:   )rz   wordr2   r2   r3   
<listcomp>5  s    zDSeleniumLicenseSearcher._clean_name_for_matching.<locals>.<listcomp>)	r-   r:   r   r   r   r   endswithappendextend)r<   r   cleanedwordsfiltered_wordsr   processed_wordshyphen_partsr2   r2   r3   r     s(   
z0SeleniumLicenseSearcher._clean_name_for_matchingcsv_namewebsite_namec           	      C   s   |dkrdS |r
|sdS |  |}|  |}| |}| |}||kr&dS | | kr0dS t||t| | t| | t| | g}t|}|| j	j
kr^dS d|ddS )z<Compare names with enhanced cleaning and return match statusrA   zNo MatchYeszNo (.1fz%))r   r   r   r   token_set_ratiotoken_sort_ratiopartial_ratioratiomaxrO   r   )	r<   r   r   cleaned_csvcleaned_websitenorm_csvnorm_websitesimilarity_methods
similarityr2   r2   r3   check_name_similarity:  s*   




z-SeleniumLicenseSearcher.check_name_similarityr8   
web_expiryc              
   C   s   |r|r|dkr
dS z;t j|dd}t j|dd}|t k }| | k}|r.|s.W dS |r5|r5W dS |s<|s<W dS |sC|rCW dS W d	S  tyb } zd
t|dd  W  Y d}~S d}~ww )z<Calculate expiry status comparison between CSV and web datesrA   rE   T)dayfirstActiveExpiredzActive - Date WrongzExpired - Date WrongUnknownzDate Error: N   )r   parser   todaydaterq   r-   )r<   r8   r   csv_dateweb_date
is_expireddates_matchrt   r2   r2   r3   calculate_expiry_statusb  s(   "z/SeleniumLicenseSearcher.calculate_expiry_statusemployeec                 C   s~   |j | jv r| j|j  }| |j|j|_d|_|S | |}| r=| j	 || j|j < W d   |S 1 s8w   Y  |S )z0Search for one employee's license using SeleniumTN)
r7   r   r   r6   rB   rF   rL   _search_with_retriesrM   r   )r<   r   cached_resultresultr2   r2   r3   search_single_license}  s   

z-SeleniumLicenseSearcher.search_single_licensec           
      C   s8  |j  st S d}t| jjD ]{}zR| j \}}zAt }| 	|||}t | }|
 rT| |j|j|_| |j|j|_||_||_|W | j| W   S W | j| n| j| w W q ty }	 zt|	}|| jjd k rtd|d   W Y d}	~	qd}	~	ww td| jj d| | jjdS )z(Try searching multiple times if it failsrH   r$   r"   NzFailed after z attempts: )rI   rJ   )r7   r:   r@   rangerO   r   r   ru   time_do_selenium_searchrM   r   r6   rB   rF   r   r8   rD   rG   rJ   rK   rv   rq   r-   sleep)
r<   r   
last_errorattemptrP   rQ   
start_timer   search_timert   r2   r2   r3   r     sB   
 z,SeleniumLicenseSearcher._search_with_retriesrP   rQ   c              
   C   s`  zd| j   || jj |ttj	df
  |ttj	df
  |ttj	df}|d| ||j td|j  |ttj	df}|d| | || | ||jW S  tys   td|j  ty } z	td	t| d
}~w ty } z	tdt| d
}~w ty } z	tdt| d
}~ww )z9Actually search the TAS government website using Seleniumri   rj   zm//*[@id="ctl00_ctl00_ctl00_ctlMainContent_ctlMainContent_MainContent_ctlOnlineSearch_txtLicenceNumberSearch"]zarguments[0].value = '';z%DEBUG: Searching for license number: zh//*[@id="ctl00_ctl00_ctl00_ctlMainContent_ctlMainContent_MainContent_ctlOnlineSearch_btnFilterMainGrid"]zarguments[0].click();zWebsite timeout for license: zPage element not found: NzWebDriver error: zSelenium search error: )r   r   rk   rO   r   rl   rm   rn   r   ro   rp   presence_of_element_locatedrf   	send_keysr7   rX   _wait_for_results_parse_search_resultsr   rq   r   r-   r   )r<   rP   rQ   r   search_inputsearch_buttonrt   r2   r2   r3   r     sV   
z+SeleniumLicenseSearcher._do_selenium_searchc                    sJ   zt |tjd  fdd}t|d| W dS  ty$   Y dS w )zWait for search results to loadi//*[@id="ctl00_ctl00_ctl00_ctlMainContent_ctlMainContent_MainContent_ctlOnlineSearch_Main_Grid"]/tbody/trc                    s   t | tjd}| kS )Nr   )r   r~   r   ro   )rh   current_rowsinitial_rowsr2   r3   table_updated  s
   z@SeleniumLicenseSearcher._wait_for_results.<locals>.table_updated
   N)r   r~   r   ro   r   rl   r   )r<   rP   rQ   r   r2   r   r3   r     s   z)SeleniumLicenseSearcher._wait_for_resultslicence_numberc                 C   sF  z| tjd}t|dkrt W S |dd D ]q}z]| tjd}t|dk r*W q|d j }||vr7W q|d j }|d j }z|d tjd	}	|	j }
W n   |d j }
Y t|rf|nd
|
rk|
nd
|rp|nd
dW   W S  t	y } zW Y d}~qd}~ww t W S  t	y } z	t	dt
| d}~ww )z5Parse search results and extract relevant informationr   r$   Ntd   r   r   rw   divrA   )rB   rC   rD   zError parsing search results: )r~   r   ro   r   r@   TAG_NAMEtextr:   find_elementrq   r-   )r<   rP   r   rowsrowcellslicence_cellr   expirylicence_type_divlicence_typert   r2   r2   r3   r     sH   


z-SeleniumLicenseSearcher._parse_search_resultsN)r)   r*   r+   r,   r   rN   rW   r-   r   r   r   r   r4   r@   r   r   r   re   r   r   r   r   r2   r2   r2   r3   r      s     )()
7r   c                   @   s.   e Zd ZdZedededee fddZ	dS )SimpleCSVHandlerz"Reads employee data from CSV files	file_pathrO   r>   c              
      s  zt j| tdd  jj jdd _g d} fdd|D }|r5tdd	| d
t j dg } 	 D ]9\}}t
|d |d |d |d |d d}|  | rt|| |jrtt||jkrttd|j d  nq;|s{tdg }t }	d}
|D ]}|j|	vr|	|j || q|
d7 }
q|
dkrtd|
 d |W S  ty } z
tdt|   d}~ww )z Load employee data from CSV fileF)dtype	na_filteru   ﻿rH   )Payroll NumberEmployee NameLicense NumberExpiry/Update  Datec                    s   g | ]	}| j vr|qS r2   )columns)rz   coldfr2   r3   r   O  s    z7SimpleCSVHandler.load_employee_data.<locals>.<listcomp>z"
ERROR: Missing required columns: r   z

Your CSV file MUST have these exact column names:
- Payroll Number
- Employee Name
- License Number
- Expiry/Update  Date

Current columns in your file: z
                r   r   r   r   r   )r5   r6   r7   r8   r9   z!TEST MODE: Processing only first z recordsz2ERROR: No valid employee records found in CSV filer   r$   zNOTE: Removed z duplicate license numberszERROR reading CSV file: N)pdread_csvr-   r   r:   replace
ValueErrorr   listiterrowsr4   r=   r?   r   r&   r   r'   rX   setr7   addrq   )r   rO   required_columnsmissing_columns	employeesindexr   r   unique_employeesseen_licensesduplicates_removedrt   r2   r   r3   load_employee_dataD  sZ   	



z#SimpleCSVHandler.load_employee_dataN)
r)   r*   r+   r,   staticmethodr-   r   r   r4   r  r2   r2   r2   r3   r   A       r   c                   @   st   e Zd ZdZdefddZdd Zdedefd	d
Z	dde
dedefddZde
defddZde
defddZdS )SimpleProgressTrackerz1Shows nice progress bar and processing statisticstotal_employeesc                 C   s<   || _ d| _d| _d| _d| _t | _d| _t	 | _
d S )Nr   )r
  	completed
successfulfailedcachedr   r   last_updaterS   rT   rU   )r<   r
  r2   r2   r3   rW     s   
zSimpleProgressTracker.__init__c              
   C   sd   t dd  t d| j d t d  t ddddd	dd
dddddd 	 t d  dS )zShow the processing header
U=====================================================================================z!TAS LICENSE CHECKER - PROCESSING z
 EMPLOYEESProgress<15r   Employee<25LicenseStatus<12SpeedzU-------------------------------------------------------------------------------------N)rX   r
  r;   r2   r2   r3   show_header  s
   
,z!SimpleProgressTracker.show_headerr   r   c                 C   sl  | j - |  jd7  _|jr|  jd7  _n| r"|  jd7  _n|  jd7  _W d   n1 s3w   Y  t }|| j dk rEdS || _| j| j	 d }| 
|}t|| j d}| j| d }t|jdkrt|jdd d	 n|j}t|jd
kr|jdd d	 n|j}	|jrd}
n	| rd}
nd}
td| d|dd|	dd|
dd|ddddd dS )zUpdate progress displayr$   Nr"   d   g{Gz?<         z..r      CachedSuccessFailedr   r  r  r  .0fz/minrH   T)endflush)rU   r  rL   r  rM   r  r  r   r  r
  _make_progress_barr   r   r   r6   r7   rX   )r<   r   r   current_timepercentprogress_barelapsedspeeddisplay_namedisplay_licensestatusr2   r2   r3   update_progress  sN   
.
z%SimpleProgressTracker.update_progressr    r)  widthr>   c                 C   s8   t || d }d| d||   }d| d|ddS )zCreate ASCII progress barr  Xr   [z] z5.1f%r/   )r<   r)  r1  filledbarr2   r2   r3   r'    s   z(SimpleProgressTracker._make_progress_barelapsed_timeexcel_file_pathc                 C   s   t dd  t d t d  t d| j  t d| j  t d| j  t d| j  t d| jt| jd	 d
 dd t d| |  t d| j| d dd t d|  t d  dS )zShow final processing summaryz

r  zPROCESSING COMPLETED!zTotal employees processed: zSuccessful searches: zFailed searches: zCached results: zSuccess rate: r$   r  r   r4  zTotal time: zProcessing speed: r  z employees/minutezExcel report saved: N)rX   r  r  r  r  r   _format_time)r<   r8  r9  r2   r2   r3   show_final_summary  s   
$z(SimpleProgressTracker.show_final_summarysecondsc                 C   sp   |dk r
|ddS |dk r"t |d }t |d }| d| dS t |d }t |d d }| d| dS )	z"Convert seconds to readable formatr  r$  z secondsi  zm szh mr5  )r<   r<  minutessecshoursr2   r2   r3   r:    s   z"SimpleProgressTracker._format_timeN)r    )r)   r*   r+   r,   r/   rW   r  r4   r@   r0  r0   r-   r'  r;  r:  r2   r2   r2   r3   r	    s    
,r	  c                   @   s.   e Zd ZdZedee dedefddZdS )SimpleExcelGeneratorz'Creates Excel reports with color codingresultsoriginal_file_pathr>   c                 C   s  zt |}t d}|j|j d| d }|  }t|}tj	|dd}}d}|j
|d|d |j}	|j| }
|	d	d
ddddd	d}t|jD ]5\}}|
d||| ttt||jsn|| tj  nd}tt|d dd}|
||| qM|
dd |
ddt|t|jd  |
dd W d   n1 sw   Y  t|W S  ty } z
tdt|   d}~ww )z?Create Excel report - ALL RECORDS (complete processing results)z%Y%m%d_%H%M%S_TAS_Results_z.xlsx
xlsxwriter)engineTAS_ResultsF)r  
sheet_nameTz#8C1E31whiter$   centervcenter)boldbg_color
font_colorborderalignvalign	text_wrapr   rw      2   r    NzERROR creating Excel report: )r   r   nowstrftimeparentstemcopyr   	DataFrameExcelWriterto_excelbooksheets
add_format	enumerater   writer   r   r-   emptyastypemin
set_columnset_row
autofilterfreeze_panesrq   rX   )rC  rD  original_path	timestamp
excel_pathall_resultsr   writerrI  workbook	worksheetheader_colorcol_numheader
max_length	col_widthrt   r2   r2   r3   create_excel_report  sL   
/

 
(z(SimpleExcelGenerator.create_excel_reportN)	r)   r*   r+   r,   r  r   r   r-   rv  r2   r2   r2   r3   rB    r  rB  c                   @   s|   e Zd ZdZdd Zdd Zdd Zdd	 Zd
efddZ	de
d
efddZdee d
ee fddZded
efddZdS )SeleniumTASLicenseCheckerzEMain application class - using reliable Selenium with CAPTCHA supportc                 C   s   t  | _t| j| _d | _d S rx   )r   rO   rN   r   progress_trackerr;   r2   r2   r3   rW   l  s   
z"SeleniumTASLicenseChecker.__init__c              
   C   sD  zzC|    |  }t|| j}| t|s%td W W | j	  dS | 
  | |}t||}t | jj }| j|| W n? tyQ   td Y n; ty } z'tdt|  td td td td td	 td
 W Y d}~nd}~ww W | j	  dS W | j	  dS W | j	  dS | j	  w )z0Main function - this is where everything happenszProcess cancelled by userNz*

Process stopped by user (Ctrl+C pressed)z
ERROR: z
TROUBLESHOOTING TIPS:z1. Make sure your CSV file has the exact column names: 'Payroll Number', 'Employee Name', 'License Number', 'Expiry/Update  Date'z)2. Check that Chrome browser is installedz)3. Make sure you have internet connectionz74. Solve any CAPTCHA that appears in the browser windowz<5. Try running as administrator if you get permission errors)_show_welcome_get_csv_file_from_userr   r  rO   _ask_user_to_continuer   rX   r   r   _show_captcha_warning!_process_all_employees_sequentialrB  rv  r   rx  r   r;  KeyboardInterruptrq   r-   )r<   csv_file_pathr  rC  rl  r8  rt   r2   r2   r3   runq  sB   
zSeleniumTASLicenseChecker.runc                 C   s   t d dS )zShow welcome messagez!TAS License Checker - Starting...N)rX   r;   r2   r2   r3   ry    s   z'SeleniumTASLicenseChecker._show_welcomec                 C   sL   t d t d t d t d | jjrt d t d t d t d dS )	zShow CAPTCHA warning to userr   u#   ⚠️  IMPORTANT: CAPTCHA HANDLINGr   z(The TAS website uses CAPTCHA protection.z5A browser window will open - please be ready to solvez+any CAPTCHA that appears during processing.z/Processing will pause when CAPTCHA is detected.N)rX   rO   r(   r;   r2   r2   r3   r|    s   z/SeleniumTASLicenseChecker._show_captcha_warningr>   c                 C   s   t tjdkrtjd  d}td|  ntd td td td td td	 d}|s<td
t| sItd| tdt|j	  |S )zGet CSV file path from userr$   z"'zUsing file from command line: z
Please provide your CSV file:z   You can either:z   1. Type the full file pathz-   2. Drag and drop the file into this windowz"   3. Copy and paste the file pathz
Enter CSV file path: zNo file path providedzFile not found: zFile found: )
r   sysargvr:   rX   r   rq   r   existsr   )r<   r   r2   r2   r3   rz    s   z1SeleniumTASLicenseChecker._get_csv_file_from_useremployee_countc                 C   sr   | j jrtdt|| j j d dS td| d td 	 td  }|dv r.dS |dv r4d	S td
 q )z.Ask user if they want to process the employeesz
TEST MODE: Will process z
 employeesTz
Ready to process z7Will use single browser (required for CAPTCHA handling)z"
Continue with processing? (Y/N): )yyes)nnoFz&Please enter 'y' for yes or 'n' for no)rO   r&   rX   re  r'   r   r:   lower)r<   r  responser2   r2   r3   r{    s   z/SeleniumTASLicenseChecker._ask_user_to_continuer  c                 C   s   t t|| _t| j| j}g }td t|D ]u\}}z/||}|j	|j
|j|j|j|j|j|j|jd	}|| | j|| t| jj W q ty } z6td|j dt|  |j	|j
|jdddd|jdd	}	||	 tt|d}
| j||
 W Y d}~qd}~ww |S )zBProcess all employees sequentially (required for CAPTCHA handling)z9
Starting sequential processing (required for CAPTCHA)...)	r   zLicence NumberzRolecall NamezLicence Namez
Name MatchzLicence TypezLicence ExpiryzRolecall ExpiryzExpiry Statusz
ERROR processing z: Error)rI   N)r	  r   rx  r   rO   r   rX   ra  r   r5   r7   r6   rB   rF   rC   rD   r8   rG   r   r0  r   r   r#   rq   r-   r@   )r<   r  searcherrm  ir   search_resultresult_dictrt   error_resulterror_search_resultr2   r2   r3   r}    sL   


z;SeleniumTASLicenseChecker._process_all_employees_sequentialr   c                 C   s   g }|j r
|d |jdkr|d|jdd |jdkr(|d|j  |jr5|d|j  n|d |rAd	|S d
S )z-Create informative notes for the Excel reportz!Cached result (duplicate license)r   zSearch time: z.2fr=  z	Retries: zError: zSelenium scrapingz | zProcessed successfully)rL   r   rK   rJ   rI   r   )r<   r   notesr2   r2   r3   _create_notes_for_result  s   



z2SeleniumTASLicenseChecker._create_notes_for_resultN)r)   r*   r+   r,   rW   r  ry  r|  r-   rz  r/   r1   r{  r   r4   r   r}  r@   r  r2   r2   r2   r3   rw  i  s    ,@rw  c            
   
   C   s8  zkddl m}  ddlm} ddlm} ddlm} ddlm	} | }|
d |
d |
d	 | j|d
}||d}z*|d |||jdf}|r[td W |  W dS td W |  W dS |  w  ty }	 z$tdt|	  td td td td td W Y d }	~	dS d }	~	ww )Nr   r
   r   r   r   r   r\   r]   r^   ra   r   r   ri   z Selenium connection test PASSED!Tz<License search elements not found - website may have changedFz!Selenium connection test failed: zCommon fixes:z 1. Install Google Chrome browserz"2. Update Chrome to latest version3. Run as administratorz4. Check internet connection)seleniumr   !selenium.webdriver.chrome.optionsr   selenium.webdriver.common.byr   selenium.webdriver.support.uir   selenium.webdriver.supportr   rc   re   rk   rl   r   ro   rX   r   rq   r-   )
r   r   r   r   rm   rg   rh   waitradio_optionrt   r2   r2   r3   test_selenium_connection4  sH   




r  c               
   C   s   t tjdkrtjd  } | dv rt  dS ztd td t s+td td t }|  W dS  tyB   td Y dS  t	yy } z,td	t
|  td
 td td td td td td W Y d}~dS d}~ww )zMain entry pointr$   )z--testz-ttestNzStarting TAS License Checker...z.
Testing Selenium connection to TAS website...z4Connection issues detected, but continuing anyway...zKIf all searches fail, the website may have changed or Chrome needs updatingz%
Selenium application stopped by userz
FATAL ERROR: z
SELENIUM TROUBLESHOOTING:z,1. Check your CSV file has the right columnsz'2. Install/update Google Chrome browserr  z!4. Check your internet connectionz05. Solve any CAPTCHA that appears in the browserz16. Run with --test to check Selenium connectivity)r   r  r  r  r  rX   rw  r  r~  rq   r-   )argapprt   r2   r2   r3   maing  s4   r  __main__)3r,   jsonr   pathlibr   dataclassesr   typingr   r   r   r   r  concurrent.futuresr   r	   rS   queuer  r   r  r   r  r   r  r   r  r   rm   selenium.common.exceptionsr   r   r   	rapidfuzzr   pandasr   dateutilr   r   r4   r@   rN   r   r   r	  rB  rw  r  r  r)   r2   r2   r2   r3   <module>   sR    !   SOhq L3*
