import time,re,json,requests,io,random,subprocess
import numpy as np
from PIL import Image
from scipy import ndimage
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.service import Service
BASE='http://ein38eu95792b.4656hd15.cc/geetest_page.html'
def mk():
    o=Options(); o.set_preference('dom.webdriver.enabled',False)
    o.set_preference('network.trr.mode',5)
    o.set_preference('network.proxy.type',2); o.set_preference('network.proxy.autoconfig_url','http://127.0.0.1:9999/proxy.pac')
    return webdriver.Firefox(service=Service('./gd0371/geckodriver'), options=o)
def xdo(*a): subprocess.run(['xdotool',*map(str,a)],check=False)
def solve_x(bg, sl):
    g=np.array(bg.convert('L')).astype(np.float32); sa=np.array(sl); full=sa[:,:,3]>128
    ys,xs=np.where(full); ax0,ay0=xs.min(),ys.min(); aw,ah=xs.max()-ax0+1,ys.max()-ay0+1
    am=full[ay0:ay0+ah,ax0:ax0+aw]; best=[]
    for th in range(50,141,10):
        dark=g<th; lab,n=ndimage.label(dark)
        for i in range(1,n+1):
            yy,xx=np.where(lab==i); a=len(xx)
            if a<300: continue
            x0,x1,y0,y1=xx.min(),xx.max(),yy.min(),yy.max(); w=x1-x0+1; h=y1-y0+1
            if abs(w-aw)>15 or abs(h-ah)>15: continue
            cm=lab[y0:y1+1,x0:x1+1]==i
            A=np.zeros_like(cm); hh=min(ah,cm.shape[0]); ww=min(aw,cm.shape[1]); A[:hh,:ww]=am[:hh,:ww]
            inter=(A&cm).sum(); union=(A|cm).sum(); iou=inter/union if union else 0
            best.append((iou,int(x0)-int(ax0),int(x0),int(y0),int(w),int(h)))
    if not best: return None
    best.sort(reverse=True)
    return best[0],best[:3]

for attempt in range(1,6):
    if attempt>1: time.sleep(random.uniform(8,14))
    d=mk(); d.set_page_load_timeout(40)
    try:
        d.set_window_position(0,0); d.set_window_size(1000,820)
        d.get(BASE); ok=False
        for _ in range(60):
            time.sleep(0.5)
            if d.execute_script("return document.querySelectorAll('.geetest_bg').length>0"): ok=True; break
        if not ok: print(attempt,'no captcha'); d.quit(); continue
        time.sleep(1.0)
        info=d.execute_script("""function r(s){var e=document.querySelector(s);if(!e)return null;var b=e.getBoundingClientRect();return {t:b.top,l:b.left,w:b.width,h:b.height,bg:getComputedStyle(e).backgroundImage};}return {bg:r('.geetest_bg'),slice:r('.geetest_slice'),slicebg:r('.geetest_slice_bg'),btn:r('.geetest_btn'),sx:window.mozInnerScreenX,sy:window.mozInnerScreenY};""")
        def dl(u):
            m=re.search(r'url\("?([^")]+)"?\)',u or '');return requests.get(m.group(1).replace('http://','https://'),timeout=20,verify=False).content
        bg=Image.open(io.BytesIO(dl(info['bg']['bg']))).convert('RGB'); sl=Image.open(io.BytesIO(dl(info['slicebg']['bg']))).convert('RGBA')
        res=solve_x(bg,sl)
        if not res: print(attempt,'no gap'); d.quit(); continue
        (iou,tl,x0,y0,w,h),top3=res
        if iou<0.55: print(attempt,'low iou',iou,top3); d.quit(); continue
        scale=info['bg']['w']/bg.size[0]; D=tl*scale
        print(f'attempt {attempt} IoU={iou:.3f} comp=({x0},{y0},{w},{h}) target_left={tl} D={D:.2f} top3={top3[:2]}')
        X=int(info['sx']+info['btn']['l']+info['btn']['w']/2); Y=int(info['sy']+info['btn']['t']+info['btn']['h']/2)
        xdo('mousemove',X,Y); time.sleep(random.uniform(0.2,0.4)); xdo('mousedown',1); time.sleep(random.uniform(0.15,0.3))
        xdo('mousemove',X-1,Y); time.sleep(0.05)
        pos=0.0; over=random.uniform(2,4)
        while pos < D+over:
            step=random.uniform(2.5,6.5) if random.random()<0.75 else random.uniform(0.6,2.0)
            pos=min(D+over,pos+step)
            xdo('mousemove',int(X+pos),Y+random.choice([0,0,0,0,1,-1])); time.sleep(random.uniform(0.012,0.045))
            if random.random()<0.06: time.sleep(random.uniform(0.04,0.12))
        time.sleep(random.uniform(0.08,0.16))
        cx=int(X+pos)
        while cx > X+D:
            cx-=random.choice([1,1,2]); xdo('mousemove',cx,Y); time.sleep(random.uniform(0.015,0.04))
        time.sleep(0.1); xdo('mouseup',1)
        val=None
        for _ in range(18):
            time.sleep(0.5); val=d.execute_script('return window.validateResult')
            if val: break
        print('  validate',json.dumps(val,ensure_ascii=False) if val else None)
        if val:
            open('gt_result.json','w').write(json.dumps(val,ensure_ascii=False)); d.quit(); break
        d.quit()
    except Exception as ex:
        print('attempt',attempt,'ERR',str(ex)[:140])
        try:d.quit()
        except:pass
