import json, re, datetime, requests

prod_path='/home/mikael/.openclaw/workspace/state/ecommerce-price-monitor.products.json'
state_dir='/home/mikael/.openclaw/workspace/state'
hist_path=state_dir+'/ecommerce-price-history.jsonl'
latest_path=state_dir+'/ecommerce-price-monitor.latest.json'

products=json.load(open(prod_path))

def get_num(s):
    s=str(s).strip()
    s=s.replace('\u00a0','').replace(' ','')
    if re.fullmatch(r'\d{1,3}(?:\.\d{3})*,\d+',s):
        s=s.replace('.','').replace(',','.')
    else:
        s=s.replace(',','.')
    try:
        return float(s)
    except: return None

def iter_jsonld(html):
    for m in re.finditer(r'<script[^>]*type=["\']application/ld\+json["\'][^>]*>(.*?)</script>', html, flags=re.I|re.S):
        txt=m.group(1).strip()
        if txt:
            yield txt

def find_from_jsonld(html, default_currency):
    best=None
    for txt in iter_jsonld(html):
        try:
            data=json.loads(txt)
        except Exception:
            continue
        items=data if isinstance(data,list) else [data]
        for it in items:
            if not isinstance(it,dict):
                continue
            at=it.get('@type')
            if at is None:
                continue
            if str(at) not in ('Product','product') and 'Product' not in str(at):
                continue
            offers=it.get('offers')
            if not offers:
                continue
            arr=offers if isinstance(offers,list) else [offers]
            for off in arr:
                if not isinstance(off,dict):
                    continue
                price=off.get('price')
                if price is None:
                    lp=off.get('lowPrice'); hp=off.get('highPrice')
                    if lp is not None:
                        price=lp
                    elif hp is not None:
                        price=hp
                if price is None:
                    continue
                pval=get_num(price)
                if pval is None:
                    continue
                cur=off.get('priceCurrency') or default_currency
                evid=f'offers.price={price}'
                cand=(pval,cur,evid)
                if best is None or cand[0]<best[0]:
                    best=cand
    return best

runAt=datetime.datetime.now().astimezone().isoformat()
results=[]
latest={'runAt':runAt,'products':[]}

default_currency=products.get('defaultCurrency','SEK')

for p in products['products']:
    url=p['url']
    trigger=p['triggerPrice']
    comp=p.get('comparator','lte')
    triggerCurrency=p.get('triggerCurrency',default_currency)
    resp=requests.get(url,headers={'User-Agent':'OpenClaw price-monitor/1.0'},timeout=30)
    resp.raise_for_status()
    html=resp.text
    found=find_from_jsonld(html, default_currency)
    if not found:
        results.append({'ok':False,'productId':p['id'],'url':url,'reason':'price-not-found-in-jsonld'})
        continue
    priceValue,currency,evidence=found
    hit = priceValue<=trigger if comp=='lte' else priceValue>=trigger
    results.append({'ok':True,'productId':p['id'],'url':url,'triggerPrice':trigger,'triggerCurrency':triggerCurrency,'comparator':comp,'currentPrice':{'priceValue':priceValue,'currency':currency,'rawPriceText':str(priceValue),'evidence':evidence},'triggerHit':hit})
    latest['products'].append({'productId':p['id'],'currentPrice':{'priceValue':priceValue,'currency':currency,'rawPriceText':str(priceValue),'evidence':evidence},'triggerPrice':trigger,'triggerHit':hit})

for r in results:
    if not r.get('ok'):
        continue
    rec={'runAt':runAt,'productId':r['productId'],'url':r['url'],'triggerPrice':r['triggerPrice'],'triggerCurrency':r['triggerCurrency'],'comparator':r['comparator'],'currentPrice':r['currentPrice'],'triggerHit':r['triggerHit']}
    with open(hist_path,'a') as f:
        f.write(json.dumps(rec,ensure_ascii=False)+'\n')

with open(latest_path,'w') as f:
    json.dump(latest,f,ensure_ascii=False,indent=2)

print(json.dumps(results,ensure_ascii=False))
