import time,re,json,requests,io,random,subprocess
import numpy as np
from PIL import Image, ImageFilter
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 gap(bg,sl,top):
    g=np.array(bg.convert('L')).astype(np.float32); sa=np.array(sl); mask=sa[:,:,3]>128
    ys,xs=np.where(mask); ax0,ay0=xs.min(),ys.min(); aw,ah=xs.max()-ax0+1,ys.max()-ay0+1
    edges=np.array(bg.convert('L').filter(ImageFilter.FIND_EDGES)).astype(np.float32)
    contour=ndimage.binary_dilation(mask)&~ndimage.binary_erosion(mask); dark=g<100
    es=[];ii=[];dd=[]
    for x in range(0,bg.size[0]-aw-ax0+1):
        reg=g[top:top+ah,x+ax0:x+ax0+aw]; m2=mask[ay0:ay0+ah,ax0:ax0+aw]
        es.append((edges[top:top+ah,x+ax0:x+ax0+aw][contour[ay0:ay0+ah,ax0:ax0+aw]].mean(),x))
        ii.append((((dark[top:top+ah,x+ax0:x+ax0+aw]&m2).sum()/m2.sum()),x))
        dd.append((reg[m2].mean(),x))
    return max(es)[1],max(ii)[1],min(dd)[1]

deltas=[0,2,-2,1,3,-1,2,0]
for attempt,delta in enumerate(deltas,1):
    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')
        top=int(round((info['slice']['t']-info['bg']['t'])*bg.size[1]/info['bg']['h'])); top=max(0,min(bg.size[1]-sl.size[1],top))
        e,i,dk=gap(bg,sl,top); base=sorted([e,i,dk])[1]; x=max(0,min(bg.size[0]-80,base+delta))
        D=x*(info['bg']['w']/bg.size[0])
        print(f'attempt {attempt} delta={delta} e={e} i={i} dk={dk} base={base} x={x} D={D:.2f}')
        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))
        # correct back to D
        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)[:120])
        try:d.quit()
        except:pass
