o
    I.il                     @   sB  d Z ddlZddlZddlZddlmZmZmZmZ ddl	m
Z
mZmZmZm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ZddlZddlZejejd ee Z!e
d	d
gdZ"G dd deZ#G dd deZ$G dd deZ%G dd deZ&G dd deZ'G dd deZ(G dd deZ)G dd deZ*G dd deZ+G dd deZ,d e-d!e-d"efd#d$Z.d%e-d"e/fd&d'Z0d(e-d"e/fd)d*Z1d+e-d"e2fd,d-Z3ed.Z4e4j5d/d/d0 d"e-fd1d2Z6d3e-d e-d4e-d5e-fd6d7Z7d3e-d"ee fd8d9Z8dwd3e-d:e-d;efd<d=Z9d3e-fd>d?Z:d@e-d e-dAe-d"ee-ef fdBdCZ;		Ddxd@e-d e-dAe-dEeee-  dFe-d"ee-ef fdGdHZ<d4e-d e-dAe-d"ee-ef fdIdJZ=dKe-d e-d"ee-ef fdLdMZ>e"j?dNe*dOedPdQ fdRe#dSedTe-fdUdVZ@e"j?dWe*dOedXdQ fdRe%dSedTe-fdYdZZAe"Bd[d3e-fd\d]ZCe"j?d^e+dOed_dQ fdRe$dTe-fd`daZDe"j?dbe,dOedcdQ fdRe&dTe-fdddeZEe"BdfedgdQ fd e-dTe-fdhdiZFe"BdjedkdQ fd e-d!e-dle-dTe-fdmdnZGe"?doedpdQ fdRe(dTe-fdqdrZHe"?dsedtdQ fdRe)dTe-fdudvZIdS )yza
Bid Processing API Routes for Minaions Tender System
To be imported and included in main app.py
    N)DictListOptionalAny)	APIRouterHTTPExceptionDependsHeaderBackgroundTasks)	BaseModelField)datetime)Path)levelz/api/bid-processingzBid Processing)prefixtagsc                   @   J   e Zd ZU edddZeed< edddZeed< eddd	Zeed
< dS )ProcessGeMBidsRequest.$Path to input gem_bids_complete.jsondescriptioninput_file_path	Tenant ID	tenant_idprocessed_bids_data.jsonOutput filenamedefaultr   output_file_nameN)	__name__
__module____qualname__r   r   str__annotations__r   r    r$   r$   >/var/www/html/minaions-tender/ai-engine/bid_processing_apis.pyr   "      
 r   c                   @   sz   e Zd ZU edddZeed< edddZeed< eddd	Zeed
< edddZ	e
ee  ed< eddd	Zeed< dS )AnalyzeSellersRequest.z Path to processed bids JSON filer   r   r   r   seller_analysis_output.jsonr   r   r   NzKeywords to filter bidssearch_keywordsanySearch mode: 'any' or 'all'search_mode)r   r    r!   r   r   r"   r#   r   r   r)   r   r   r,   r$   r$   r$   r%   r'   '   s   
 r'   c                   @   r   )ProcessEProcBidsRequest.z%Root directory containing bid foldersr   root_directoryr   r   r   r   r   r   N)	r   r    r!   r   r.   r"   r#   r   r   r$   r$   r$   r%   r-   .   r&   r-   c                   @   s6   e Zd ZU edddZeed< edddZeed< dS )GetBidAnalyticsRequest.z!Path to seller analysis JSON filer   analysis_file_pathr   r   N)r   r    r!   r   r0   r"   r#   r   r$   r$   r$   r%   r/   3   s   
 r/   c                   @   sb   e Zd ZU edddZeed< edddZeed< eddd	Zeed
< edddZ	e
e ed< dS )ExportBidsRequest.zPath to processed bids JSONr   processed_bids_filer   r   jsonzExport format: json or csvr   export_formatNz!Limit number of records to exportlimit)r   r    r!   r   r2   r"   r#   r   r4   r5   r   intr$   r$   r$   r%   r1   7   s
   
 r1   c                   @   sn   e Zd ZU edddZeeef ed< edddZ	eed< edddZ
eee  ed	< ed
ddZeed< dS )ProcessGeMBidsDirectRequest.zRaw bids JSON datar   	bids_datar   r   NKeywords to filter sellersr)   r*   r+   r   r,   )r   r    r!   r   r8   r   r"   r   r#   r   r)   r   r   r,   r$   r$   r$   r%   r7   =   s
   
 r7   c                   @   s   e Zd ZU edddZeed< edddZeed< edddZe	e
e  ed	< ed
ddZeed< edddZeed< edddZe	e ed< dS )ProcessGeMBidsFullRequest.r   r   r   r   r   Nr9   r)   r*   r+   r   r,   r3   z<Return type: 'json' (response body) or 'file' (save to disk)return_typezFull path for output file. If not provided, defaults to /tmp/bid_processing/{tenant_id}/combined_processing/seller_analysis_output.jsonoutput_file_path)r   r    r!   r   r   r"   r#   r   r)   r   r   r,   r;   r<   r$   r$   r$   r%   r:   C   s   
 r:   c                   @   sJ   e Zd ZU eed< eed< ee ed< eed< eed< eee	f ed< dS )ProcessingResultstatusmessage	file_pathprocessing_timerecord_countdetailsN)
r   r    r!   r"   r#   r   floatr6   r   r   r$   r$   r$   r%   r=   K   s   
 r=   c                   @   s^   e Zd ZU eed< eed< ee ed< eed< eed< eeee	f  ed< eee	f ed< dS )	SellerAnalyticsResultr>   r?   r@   total_sellerstotal_bids_analyzedtop_sellersanalysis_metadataN)
r   r    r!   r"   r#   r   r6   r   r   r   r$   r$   r$   r%   rE   S   s   
 rE   c                   @   s6   e Zd ZU eed< eeef ed< eeef ed< dS )BidAnalyticsResponser>   datasummaryN)r   r    r!   r"   r#   r   r   r$   r$   r$   r%   rJ   \   s   
 rJ   r   process_typereturnc                 C   s"   t d|  | }|jddd |S )z$Get tenant-specific output directory/tmp/bid_processingTparentsexist_ok)r   mkdir)r   rM   base_dirr$   r$   r%   get_tenant_output_dire   s   rU   r@   c                 C      t j| S )zVerify that a file exists)ospathexists)r@   r$   r$   r%   verify_file_existsk      rZ   dir_pathc                 C   rV   )zVerify that a directory exists)rW   rX   isdir)r\   r$   r$   r%   verify_directory_existso   r[   r^   root_dirc                 C   s   t | }d}d}d}| sdS | D ]-}| rA|d7 }tdd | D }tdd | D }|r=|r=|d7 }q|d7 }q|||fS )zz
    Count folders with required files (PDF and JSON)
    Returns: (total_folders, folders_with_files, missing_count)
    r   )r   r   r      c                 s   s&    | ]}|  r|j d kV  qdS )z.pdfN)is_filesuffixlower.0fr$   r$   r%   	<genexpr>   s   $ z4count_folders_with_required_files.<locals>.<genexpr>c                 s   s"    | ]}|  r|jd kV  qdS )zstage_summary_data.jsonN)ra   namerd   r$   r$   r%   rg      s     )r   rY   iterdiris_dirr*   )r_   	root_pathtotal_foldersvalid_foldersinvalid_foldersfolderhas_pdfhas_jsonr$   r$   r%   !count_folders_with_required_filess   s    

rr   z"/tmp/bid_processing/.task_registryTrP   c                   C   s   t t S )zGenerate unique task ID)r"   uuiduuid4r$   r$   r$   r%   create_task_id   r[   ru   task_idr.   r   c                 C   sr   t |  d }| |||t  dd}t|d}t|| W d   n1 s*w   Y  td|   dS )z*Save task metadata for later status lookup.json
processing)rv   r   r.   r   
created_atr>   wNzTask metadata saved for )	TASK_REGISTRY_DIRr   now	isoformatopenr3   dumploggerinfo)rv   r   r.   r   	task_filemetadatarf   r$   r$   r%   save_task_metadata   s   
r   c                 C   sN   t |  d }| r%t|d}t|W  d   S 1 s w   Y  dS )zRetrieve task metadatarw   rN)r{   rY   r~   r3   load)rv   r   rf   r$   r$   r%   get_task_metadata   s    r   r>   result_datac                 C   s   t |  d }| r_t|d}t|}W d   n1 s w   Y  ||d< t  |d< |r7||d< t|d}t|| W d   n1 sMw   Y  t	
d|  d	|  dS dS )
zUpdate task status and resultrw   r   Nr>   completed_atresultrz   Task z status updated to )r{   rY   r~   r3   r   r   r|   r}   r   r   r   )rv   r>   r   r   rf   r   r$   r$   r%   update_task_status   s   r   c              
   C   s   z7t d|   t| }|st d|   W dS t|d |d |d }t| d| t d|  d	 W dS  tyg } z$t jd|  d
t| dd t| dt|t|j	d W Y d}~dS d}~ww )z-Wrapper to run handler and update task statusz(Starting background processing for task zTask metadata not found for Nr.   r   r   	completedr   z completed successfullyz	 failed: Texc_infofailederror
error_type)
r   r   r   r   process_eproc_bids_handlerr   	Exceptionr"   typer   )rv   r   r   er$   r$   r%   %process_eproc_bids_background_wrapper   s*   r   
input_fileoutput_filec                 C   s  t   }ztd|  t| std|  t|d}|| }t| ddd}t|}W d   n1 s8w   Y  tdt	|
d	g  d
 t|}t|ddd}tj||ddd W d   n1 slw   Y  t   | }	tdd |d	 D }
ddt	|d	  dt||	t	|d	 |
|
di dd}td|	dd |W S  ty } z(tjdt| dd ddt| dt   | ddt|idW  Y d}~S d}~ww ) zProcess GeM bid dataz'Starting GeM bid processing for tenant Input file not found: gem_processingr   utf-8encodingNLoaded bidsz bids from input filerz      Findentensure_asciic                 s   8    | ]}t |d i di di dg V  qdS detailedInfosections
evaluationsellersNlengetre   bidr$   r$   r%   rg     
    &
z+process_gem_bids_handler.<locals>.<genexpr>successSuccessfully processed  bidsr   )rF   r   r>   r?   r@   rA   rB   rC   z GeM bid processing completed in .2fszError processing GeM bids: Tr   r   zFailed to process GeM bids: r   )timer   r   rZ   FileNotFoundErrorrU   r~   r3   r   r   r   
gem_refineprocess_bids_datar   sumr"   r   r   )r   r   r   
start_time
output_diroutput_pathrf   rK   processed_datarA   rF   r   r   r$   r$   r%   process_gem_bids_handler   sR   





r   r*   r)   r,   c                 C   s  t   }ztd|  t| std|  t|d}|| }tj| t|||d t	|ddd}t
|}	W d   n1 sCw   Y  t   | }
|	d	g dd
 }ddt|	d	g  dt||	d ddtdd |	d	g D ||	d d|	d d|	d d|
dd}td|
dd |W S  ty } z*tjdt| dd ddt| dddg t|t   | d dW  Y d}~S d}~ww )!z#Analyze sellers from processed bidsz$Starting seller analysis for tenant r   seller_analysisr)   r,   r   r   r   Nr      r   zSuccessfully analyzed  unique sellersr   total_unique_sellersr   c                 s       | ]	}| d dV  qdS total_bids_appliedr   Nr   re   r   r$   r$   r%   rg   G      z*analyze_sellers_handler.<locals>.<genexpr>analysis_datesource_total_bidsfilter_applied)r   r   r   rA   )r>   r?   r@   rF   rG   rH   rI   zSeller analysis completed in r   r   zError analyzing sellers: Tr   r   zFailed to analyze sellers: )r   rA   )r   r   r   rZ   r   rU   seller_statsanalyze_biddersr"   r~   r3   r   r   r   r   r   r   )r   r   r   r)   r,   r   r   r   rf   resultsrA   rH   r   r   r$   r$   r%   analyze_sellers_handler!  sX   
r   c                 C   s  t   }ztd|  td|   t| s td|  t|d}|| }t| \}}}td| d| d| d |d	krJtd
|  |d	krRtdt	| t
|td}	td| d |	 }
t   | }t|
dg }tdd |
dg D }dd| d| dt
||||||||
di |
di dd	|
di ddddd}td|dd td | d!| d" |W S  ty } z'td#t
|  d$d%t
| d&t   | d	t
|d'd(dW  Y d&}~S d&}~w ty5 } z'td)t
|  d$d*t
| d&t   | d	t
|d+d(dW  Y d&}~S d&}~w tyj } z)tjd,t
| d-d. d$d/t
| d&t   | d	t
|d0d(dW  Y d&}~S d&}~ww )1ue  
    Process eproc bid data from work order PDFs and JSON files
    
    Expected folder structure:
    root_directory/
    ├── folder_1/
    │   ├── work_order.pdf (or any .pdf file)
    │   └── stage_summary_data.json
    ├── folder_2/
    │   ├── work_order.pdf
    │   └── stage_summary_data.json
    ...
    z)Starting eproc bid processing for tenant zRoot directory: zRoot directory not found: eproc_processingzFound z
 folders: z valid, z invalidr   zNo folders found in z]No valid bid folders found. Each folder must contain a PDF file and 'stage_summary_data.json'ANTHROPIC_API_KEYzStarting to process z valid folders...r   c                 s   r   r   r   r   r$   r$   r%   rg     r   z-process_eproc_bids_handler.<locals>.<genexpr>r   r   z eproc bids from z foldersr   withDetailedInfodetailFetchSuccessz0%)bids_with_detailed_infodetail_fetch_success_rate)rF   folders_processedfolders_skippedtotal_folders_foundr   processing_summaryr   z"eproc bid processing completed in r   r   z
Processed z bids with r   z%Directory error in eproc processing: r   zDirectory error: Ndirectory_not_foundr   z&Validation error in eproc processing: zValidation error: validation_errorzError processing eproc bids: Tr   zFailed to process eproc bids: processing_error)r   r   r   r^   NotADirectoryErrorrU   rr   
ValueErroreprocBidProcessorr"   rW   getenvprocess_all_foldersr   r   r   r   r   )r.   r   r   r   r   r   rl   rm   rn   	processorr   rA   
total_bidsrF   final_resultr   r$   r$   r%   r   `  s   



	
	
r   analysis_filec                 C   s  zt d|  t| std|  t| ddd}t|}W d   n1 s+w   Y  |dg }|di }td	d
 |D }tdd
 |D }t	||tdd
 |D tdd
 |D ||dd|rp|t	| nd|dkr{|| d nd|dd t
tdd |D t	dd |D t	dd |D dd}d||t  dd}	|	W S  ty }
 z!t jdt|
 dd di t|
t  d dW  Y d}
~
S d}
~
ww )!$Get analytics from bid analysis dataz$Generating bid analytics for tenant zAnalysis file not found: r   r   r   Nr   r   c                 s   r   r   r   r   r$   r$   r%   rg     r   z,get_bid_analytics_handler.<locals>.<genexpr>c                 s   r   total_bids_won_l1r   Nr   r   r$   r$   r%   rg     r   c                 s   r   total_bids_qualifiedr   Nr   r   r$   r$   r%   rg     r   c                 s   r   total_bids_disqualifiedr   Nr   r   r$   r$   r%   rg     r   total_amount_won_all_l1_bidsu   ₹0.00r   d   
   c                 S   s"   g | ]}| d g D ]}|q
qS )seller_locationsr   )re   r   locr$   r$   r%   
<listcomp>  s   " z-get_bid_analytics_handler.<locals>.<listcomp>c                 S       g | ]}d | ddv r|qS )MSEspecial_status r   r   r$   r$   r%   r          c                 S   r   )MIIr   r   r   r   r$   r$   r%   r     r   )msemii)rF   r   total_qualifiedtotal_disqualifiedtotal_l1_winnerstotal_amount_wonaverage_bids_per_sellersuccess_ratetop_10_sellersr   special_categoriesr   )r   generated_at)r>   rK   rL   zError generating analytics: Tr   r   )r   r  )r   r   rZ   r   r~   r3   r   r   r   r   listsetr   r|   r}   r   r   r"   )r   r   rf   analysis_datar   r   r   r  	analyticsr   r   r$   r$   r%   get_bid_analytics_handler  sP   


	r  z/process/gem-bids)response_modelc                   C      t jddS NBID_PROCESSING_API_KEYzdefault-keyrW   environr   r$   r$   r$   r%   <lambda>      r  requestbackground_tasksapi_keyc              
      sz   zt | j| j| j}|d dkrtd|d dtdi |W S  ty< } ztd|  tdt	|dd}~ww )	z"Process GeM bid data and refine itr>   r     r?   status_codedetailz$Error in process_gem_bids endpoint: Nr$   )
r   r   r   r   r   r=   r   r   r   r"   )r  r  r  r   r   r$   r$   r%   process_gem_bids	  s   r  z/process/eproc-bidsc                   C   r  r  r  r$   r$   r$   r%   r  (  r  c              
      s   z=t d| j  t }t d| d| j  t|| j| j| j |t| t	dd| dddd|d	| d
dW S  t
y\ } zt jd| dd tdt|dd}~ww )z
    Process eproc bid data from work order PDFs and JSON files (Non-blocking)
    
    Returns task_id that can be used to check status via GET /process/eproc-bids/status/{task_id}
    z.Received eproc processing request for tenant: zCreated task z for tenant rx   z$eproc processing started - task ID: Nr   processing_in_backgroundz./api/bid-processing/process/eproc-bids/status/)r>   rv   poll_urlr   z#Error initiating eproc processing: Tr   r  r  )r   r   r   ru   r   r.   r   add_taskr   r=   r   r   r   r"   )r  r  r  rv   r   r$   r$   r%   process_eproc_bids$  s>   r!  z$/process/eproc-bids/status/{task_id}c                    s  zt d|   t| }|s#t d|   d| dd|  dW S |d dkrNt|d	 }t |  d
 }d| |d|d	t	|ddddW S |d dkr|di }d| |d|d	|d|d|d|d|d|dd
W S |d dkr|di }d| |d|d	|d|d|dd|d dW S d| |d d|d  dW S  t
y } zt jd | d!d" d| t|d#dW  Y d$}~S d$}~ww )%z
    Check processing status using task_id
    
    Returns:
    - processing: Still running
    - completed: Finished successfully with results
    - failed: Error occurred
    - error: Task not found or invalid
    zChecking status for task zTask not found: r   zTask not foundzNo task found with ID: )r>   rv   r   r?   r>   rx   ry   <   r   r`   z5Processing in progress. Check again in a few minutes.z#5-15 minutes depending on file size)r>   rv   r   ry   elapsed_minutesr?   estimated_waitr   r   r   rB   r@   rA   r?   rC   )
r>   rv   r   ry   r   rB   r@   rA   r?   rC   r   r   zProcessing failed: )r>   rv   r   ry   r   r   r   r?   unknownzUnknown status: )r>   rv   metadata_statusr?   zError checking task status: Tr   zError checking task statusN)r   r   r   warningr   fromisoformatr|   total_secondsr   roundr   r   r"   )rv   r   elapsedr#  r   r   r$   r$   r%   get_eproc_statusZ  sx   
r,  z/analyze/sellersc                   C   r  r  r  r$   r$   r$   r%   r    r  c              
      s   z$t | j| j| j| j| jd}|d dkrtd|d dtd	i |W S  tyA } zt	
d|  tdt|dd}~ww )
z'Analyze sellers from processed bid datar   r>   r   r  r?   r  z#Error in analyze_sellers endpoint: Nr$   )r   r   r   r   r)   r,   r   rE   r   r   r   r"   r  r  r   r   r$   r$   r%   analyze_sellers  s"   r.  z/analyze/bidsc                   C   r  r  r  r$   r$   r$   r%   r    r  c              
      s~   z!t | j| j}|d dkrtd|d dddtd
i |W S  ty> } ztd|  tdt	|dd	}~ww )r   r>   r   r  rL   r   zUnknown errorr  z%Error in get_bid_analytics endpoint: Nr$   )
r  r0   r   r   r   rJ   r   r   r   r"   r-  r$   r$   r%   get_bid_analytics  s   r/  z/processing-status/{tenant_id}c                   C   r  r  r  r$   r$   r$   r%   r    r  c              
      s   zGt d|  }| s| dddW S i }| D ](}| rAt|d}t|dd |D |r:tdd |D nd	d
||j< q| d|dW S  t	yd } zt
d|  tdt|dd	}~ww )z*Get status of processing jobs for a tenantrO   no_processingz+No processing history found for this tenant)r   r>   r?   z*.jsonc                 S   s   g | ]}|j qS r$   )rh   rd   r$   r$   r%   r   #  s    z)get_processing_status.<locals>.<listcomp>c                 S   s    g | ]}t | j qS r$   )r   fromtimestampstatst_mtimer}   rd   r$   r$   r%   r   $  r   N)
file_countfileslast_modifiedr   )r   r>   processing_historyz!Error getting processing status: r  r  )r   rY   ri   rj   r	  globr   maxrh   r   r   r   r   r"   )r   r  output_baseprocessing_dirsrM   r5  r   r$   r$   r%   get_processing_status  s4   r<  z"/export/{tenant_id}/{process_type}c                   C   r  r  r  r$   r$   r$   r%   r  6  r  	file_namec           	   
      s   z:t | |}|| }| stdd| dt|ddd}t|}W d   n1 s/w   Y  d| ||d	W S  tyC     ty^ } ztd
|  tdt	|dd}~ww )zExport processed bid datai  zFile not found: r  r   r   r   Nr   )r>   r   r=  rK   zError exporting data: r  )
rU   rY   r   r~   r3   r   r   r   r   r"   )	r   rM   r=  r  r   r@   rf   rK   r   r$   r$   r%   export_processed_data1  s*   
r>  z/process-and-analyzec                   C   r  r  r  r$   r$   r$   r%   r  T  r  c                    s  t   }zNtd| j  | jrt| jtstdddtd | j}d|vr<t	 
 t|dg d|d< d|vrFtdd	dt|}td
t|d  d t| jd}|dtt    d }t|ddd}tj||ddd W d   n1 sw   Y  td |dtt    d }tjt|t|| j| jd td t|ddd}t|}	W d   n1 sw   Y  t   | }
|	dg }tdd |D }tdd |D }d| j|
d
t|d  d t| d!d"t|d td#d |d D d$d"t||td%d |D td&d |D ||d'kr.|| d( nd'd)d*||	|dd+ t	 
 | j| jd,d-	}td.|
d/d0 |W S  ty]     ty } ztjd1t| d2d3 td4d5t| dd}~ww )6a#  
    Combined endpoint: Process GeM bids and analyze sellers in one call
    Accepts JSON data directly, returns processed and analyzed data
    
    Steps:
    1. Process GeM bid data (refine_gem_bid_data)
    2. Analyze sellers (seller_analysis)
    3. Return combined results as JSON
    @Starting combined GeM processing and seller analysis for tenant   z'Invalid bids_data: must be a dictionaryr  zStep 1: Processing GeM bids...r   r   	scrapedAt	totalBidsz*Invalid bids_data: must contain 'bids' keyr   r   combined_processing
processed_rw   rz   r   r   r   Fr   NzStep 2: Analyzing sellers...	analysis_r   zSeller analysis completedr   r   c                 s   r   r   r   r   r$   r$   r%   rg     r   z/process_and_analyze_gem_bids.<locals>.<genexpr>c                 s   r   r   r   r   r$   r$   r%   rg     r   r    bids and analyzed  sellersr   c                 s   r   r   r   r   r$   r$   r%   rg     r   )r>   bids_processedtotal_sellers_foundc                 s   r   r   r   r   r$   r$   r%   rg     r   c                 s   r   r   r   r   r$   r$   r%   rg     r   r   r   )r>   unique_sellersrG   r   r  r  r  )step_1_gem_processingstep_2_seller_analysisr   )processed_atkeywords_filteredr,   )	r>   r   rA   r?   r   processed_bids_dataseller_analysis_datar  r   z.Combined processing completed successfully in r   r   z'Error in process_and_analyze_gem_bids: Tr   r  $Failed to process and analyze bids: )r   r   r   r   r8   
isinstancedictr   r   r|   r}   r   r   r   r   rU   r6   r~   r3   r   r   r   r"   r)   r,   r   r   r   r   )r  r  r   data_to_processr   r   processed_file_pathrf   r0   analysis_resultsrA   r   r   r  responser   r$   r$   r%   process_and_analyze_gem_bidsQ  s   






	

"rY  z/process-and-analyze-filec                   C   r  r  r  r$   r$   r$   r%   r    r  c              
      sN  t   }ztd| j  td| j  | jdvr$tdddt| js3tdd| j dtd| j  t| jd	d
d}t	
|}W d   n1 sTw   Y  tdt|dg  d td d|vrt  t|dg d|d< t|}tdt|d  d t| jd}tt   }|d| d }|d| d }	t|dd
d}t	j||ddd W d   n1 sw   Y  td tjt|t|	| j| jd t|	d	d
d}t	
|}
W d   n1 sw   Y  t   | }|
dg }td d! |D }td"d! |D }|t|d t||td#d! |D td$d! |D ||d%krD|| d& nd%d'}z
|  |	  W n tym } ztd(|  W Y d}~nd}~ww | jd)krtd* |
 }||d+< d,|d-< td.|d/d0 |W S | jrt | j}|j!j"d1d1d2 n|d3 }td4|  t|dd
d}t	j|
|ddd W d   n	1 sw   Y  td5|d/d0 d,dt|d  d6t| d7t||t|t||d8d9W S  ty     ty& } ztj#d:t| d1d; td<d=t| dd}~ww )>a  
    Combined endpoint: Process GeM bids from file and analyze sellers in ONE call
    
    Parameters:
    - input_file_path: Path to input JSON file
    - tenant_id: Tenant identifier
    - search_keywords: Optional keywords to filter sellers
    - search_mode: 'any' or 'all' for keyword filtering
    - return_type: 'json' (return in response body) or 'file' (save to disk)
    - output_file_path: Optional custom output file path
    
    Returns ONLY the final seller analysis (no intermediate files)
    r?  zReturn type: )r3   filer@  z$return_type must be 'json' or 'file'r  r   z Step 1: Loading bids from file: r   r   r   Nr   r   z bids from filezStep 2: Processing GeM bids...r   rA  r   r   rD  z.temp_processed_rw   z.temp_analysis_rz   r   Fr   zStep 3: Analyzing sellers...r   r   c                 s   r   r   r   r   r$   r$   r%   rg     r   z4process_and_analyze_gem_bids_file.<locals>.<genexpr>c                 s   r   r   r   r   r$   r$   r%   rg     r   c                 s   r   r   r   r   r$   r$   r%   rg     r   c                 s   r   r   r   r   r$   r$   r%   rg     r   r   r   )rA   rI  rK  rG   r   r  r  r  zCould not clean up temp files: r3   z2Returning seller analysis as JSON in response bodyr   r   r>   zProcessing completed in r   r   TrP   r(   zSaving seller analysis to: z"Processing completed and saved in rG  rH  )r   statsr   z,Error in process_and_analyze_gem_bids_file: r   r  rR  )$r   r   r   r   r;   r   rZ   r   r~   r3   r   r   r   r   r|   r}   r   r   rU   r6   r   r   r   r"   r)   r,   r   unlinkr   r'  copyr<   r   parentrS   r   )r  r  r   rf   r8   r   r   	timestamptemp_processed_filetemp_analysis_filerW  rA   r   r   r  summary_datar   response_datar<   r$   r$   r%   !process_and_analyze_gem_bids_file  s   









rd  )N)Nr*   )J__doc__rW   r3   loggingtypingr   r   r   r   fastapir   r   r   r	   r
   pydanticr   r   r   rs   r   pathlibr   refine_gem_bid_datar   r   r   process_eproc_datar   basicConfigINFO	getLoggerr   r   routerr   r'   r-   r/   r1   r7   r:   r=   rE   rJ   r"   rU   boolrZ   r^   tuplerr   r{   rS   ru   r   r   r   r   r   r   r   r  postr  r!  r   r,  r.  r/  r<  r>  rY  rd  r$   r$   r$   r%   <module>   s   
		" >


"?o:

5 


$

w
