o
    i+(                     @   s   d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZm	Z	 ddl
mZ ddlmZ e Z
e Ze eZedddZdd Zdd
dZdd Zdd ZdS )    N)datetime	timedelta   )XaiTokenManager)XaiCachei  c                 C   s0   t j| d dd}t j|dtdd| d< | S )zTConverts a DataFrame's timestamp column from Keepa Time Minutes to datetime objects.	timestampcoerce)errorsm)unitoriginzdatetime64[ns])pd
to_numericto_datetimeKEEPA_EPOCHastype)dfnumeric_timestamps r   :/var/www/agentarbitrage/keepa_deals/xai_sales_inference.py_convert_ktm_to_datetime   s   r   d   c              
      sB  |  d |  dg }t|trt|dk rdS |d }|d }|d }|r(|s*dS  fdd	}||d
}||d}||d}	|du sG|du rIdS t t|d }
||d |
k d }||d |
k d }||g}|	dur}|	|	d |
k d }|| t	|
}|rt
dd |D rt|g}n%t|  jdd}|jd |krtt|g|g jdd}td|i}z&tj||ddd}tj||ddd}|	durtj||	ddd}nd|d< W n ty } ztd  d|  W Y d}~dS d}~ww |jd
dgd}|jrdS g }|d |d d}d}| D ]s\}}|d d}t|d
 sAt|d
 nd}t|d sUd|d d d nd}t|d sl|d dkrlt|d nd}|||f}||kr|| d!| d!| d!|  |}|d"7 }|d#kr|d$  nq(d%|S )&z
    Extracts relevant history (Rank, Used Price, Used Offer Count) for the last n days
    and formats it as a compact time-series text for the LLM.
    Ensures initial state (at start of window) is captured.
    asincsv   N         c              
      s   | rt | dk r
d S z%t| }t |d dkr|d d }tj|ddd|gd}t|W S  tyM } zt	d  d|  W Y d }~d S d }~ww )Nr   r   r   )columnsz#Error converting history to DF for : )
lennparrayr   	DataFramereshaper   	Exceptionloggerwarning)histcol_namearrr   er   r   r   to_df1   s   

z%format_history_for_xai.<locals>.to_dfRankPriceOffersdaysr   c                 s   s    | ]}|j V  qd S )N)empty).0tsr   r   r   	<genexpr>W   s    z)format_history_for_xai.<locals>.<genexpr>T)dropr   backward)on	directionzN/AzError during merge_asof for r    )subsetz!Time | Rank | Used Price | Offersz---|---|---|---z%Y-%m-%d %H:%M-$r   z.2fz | r      z... (truncated) ...
)get
isinstancelistr!   r   nowr   appendr   	TimestampallSeriesconcatsort_valuesdrop_duplicatesreset_indexilocr$   
merge_asofr&   r'   errordropnar4   iterrowsstrftimeisnaintjoin)productr3   csv_datarank_historyused_price_historyused_offer_count_historyr.   df_rankdf_price	df_offers
start_datets_rankts_pricetimestamps_list	ts_offersstart_date_ts
timestamps	df_mergedr,   lineslast_row_valscount_rowts_strrankpriceofferscurrent_valsr   r-   r   format_history_for_xai   s   





"

 (.

 


rp   c              
   C   s  t d}|std dS |dd}|dg }|r"|d d nd}t s3td	| d
 dS d| d| d|  d}d|dgdddd}d| dd}zutjddd}	|	j	d||d}
|

  |
 d d d d }z0d |v r|d d! d"d  }nd"|v r|d"d!  }t|}|W W  d   W S  tjy   td#|  Y W d   W dS w 1 sw   Y  W dS  ty } ztd$|  W Y d}~dS d}~ww )%z@
    Queries XAI to identify sales in the provided history.
    	XAI_TOKENzNo XAI_TOKEN found.NtitleUnknowncategoryTreer   namez=XAI daily limit reached. Cannot perform sales inference for 'z'.z
    You are an expert Amazon Arbitrage Analyst.
    Your goal is to identify "Inferred Sales" from the following historical data for the product: "z" (a  ).

    Logic for a sale:
    - Typically, a drop in "Offers" (Used Offer Count) suggests a unit was sold.
    - However, offers can also be removed by sellers.
    - A corresponding drop (improvement) in "Rank" (Sales Rank gets smaller) shortly after an offer drop is a strong confirmation of a sale.
    - Sometimes Rank drops without an offer drop (if stock depth > 1).
    - Sometimes Offers drop without a rank drop (delisted).
    - Sometimes Rank drops and recovers between data points (sparse data).

    Task:
    Analyze the provided time-series data. Identify the most likely "Sold Price" for any VALID sales you detect in this period.
    Ignore price drops that look like repricing wars unless accompanied by a sale signal.

    Return a JSON object with:
    1. "sales_found": count of confirmed sales.
    2. "events": list of objects, each with {"date": "YYYY-MM-DD", "price": float (number only)}.
    3. "estimated_market_price": your best estimate of the current true market value for a Used copy based on these sales.
    4. "confidence": "High", "Medium", or "Low".
    5. "reasoning": brief explanation.

    Data (Last ~100 days):
    z
    user)rolecontentzgrok-4-fast-reasoningg?i  )messagesmodeltemperature
max_tokenszBearer zapplication/json)AuthorizationzContent-Typeg      N@)timeoutz$https://api.x.ai/v1/chat/completions)headersjsonchoicesr   messagerx   z```jsonr   z```z&Failed to parse XAI response as JSON: z"XAI Error during sales inference: )osgetenvr'   r(   rA   xai_token_managerrequest_permissionhttpxClientpostraise_for_statusr   splitstriploadsJSONDecodeErrorrO   r&   )history_textrV   api_keyrr   cat_treecategorypromptpayloadr   clientresponserx   resultr,   r   r   r   query_xai_sales_inference   s^   



r   c                 C   s8  |  di }| ddgd d }|r|dkrdS t| dd}|s#dS t|| }|r| d	d
v r| dg }g }|D ]J}z+| d}| d}	|rg|	rgt|dtdd }
tt|	d }||
|d W q; t	y } zt
d| d|  W Y d}~q;d}~ww |rt
dt| d|  d  |S dS )zg
    Wrapper to call XAI inference if eligible.
    Returns a list of sale events (dicts) or None.
    statscurrentN   r   i r   r2   
confidence)HighMediumeventsdaterm   z%Y-%m-%dr   )hours)event_timestampinferred_sale_price_centszError parsing XAI event r    zXAI Rescued z sales for ASIN r   )rA   rp   r   r   strptimer   rT   floatrE   r&   r'   r(   infor!   )rV   r   current_rankr   r   r   confirmed_saleseventdate_strrm   dtprice_centsr,   r   r   r   infer_sales_with_xai   s>   


" r   )r   )loggingpandasr   numpyr"   r   r   r   r   r   r   r   	xai_cacher   	getLogger__name__r'   r   r   rp   r   r   r   r   r   r   <module>   s"    

tM