"""
sign 수정 전(old_poseRobot_test.html) vs 현재(DOZIKWORKS_OS_v4_pathcreate.dc.html)
STL world 위치 비교 — 현재 파일 수정 없음.
"""
import asyncio, math
from playwright.async_api import async_playwright

JS = """
() => {
    var app = window.__dzw;
    var T = app._T;
    if(!app || !T) return {err:'no app'};
    app._grp.updateMatrixWorld(true);

    function wpos(obj) {
        var v = new T.Vector3();
        obj.getWorldPosition(v);
        return [+(v.x*1000).toFixed(1), +(v.y*1000).toFixed(1), +(v.z*1000).toFixed(1)];
    }
    function dist(a,b){var dx=a[0]-b[0],dy=a[1]-b[1],dz=a[2]-b[2];return +Math.sqrt(dx*dx+dy*dy+dz*dz).toFixed(1);}

    var gj = app.gj;
    var out = {joints:{}, stlBB:{}, angRz:{}};

    ['S','L','U','R','B','T'].forEach(function(a){
        var ag=gj[a]; if(!ag)return;
        out.joints[a] = wpos(ag.parent);
        out.angRz[a]  = +(ag.rotation.z*180/Math.PI).toFixed(2);

        var box = new T.Box3(); var has=false;
        ag.children.forEach(function(c){
            if(c.isMesh&&c.geometry&&c.geometry.attributes&&c.geometry.attributes.position){
                var mb=new T.Box3(); mb.setFromObject(c); box.union(mb); has=true;
            }
        });
        if(has){
            var cen=new T.Vector3(); box.getCenter(cen);
            out.stlBB[a]=[+(cen.x*1000).toFixed(1),+(cen.y*1000).toFixed(1),+(cen.z*1000).toFixed(1)];
        }
    });

    // poseRobot 방식 판별
    var src = (app.poseRobot||'').toString();
    out.hasSGN = src.includes('SGN');

    return out;
}
"""

JS_SET_CAM = """(args)=>{
    var app=window.__dzw;
    if(!app||!app.orbit)return;
    app.orbit.theta=args.theta; app.orbit.phi=args.phi; app.orbit.r=args.r;
    if(app.orbit.tgt)app.orbit.tgt.set(0,0,0.5);
    if(app.updateCam)app.updateCam();
}"""

async def measure(pg, url, label, shot):
    await pg.goto(url)
    await pg.wait_for_timeout(20000)
    r = await pg.evaluate(JS)
    if 'err' in r:
        print(f"  [{label}] ERR: {r}")
        return None
    # 카메라 FRONT
    await pg.evaluate(JS_SET_CAM, {'theta': -math.pi/2, 'phi': math.pi/2*0.6, 'r': 3.5})
    await pg.wait_for_timeout(300)
    await pg.screenshot(path=shot)
    return r

async def main():
    BASE = 'http://localhost:8090'
    OLD  = f'{BASE}/old_poseRobot_test.html'
    NEW  = f'{BASE}/DOZIKWORKS_OS_v4_pathcreate.dc.html'

    async with async_playwright() as p:
        br = await p.chromium.launch(headless=True)
        pg = await br.new_page()
        await pg.set_viewport_size({'width':1536,'height':1024})

        r_old = await measure(pg, OLD, 'OLD', 'robot_old_front.png')
        r_new = await measure(pg, NEW, 'NEW', 'robot_new_front.png')
        await br.close()

    if not r_old or not r_new:
        print("측정 실패")
        return

    print(f"OLD hasSGN={r_old['hasSGN']}  /  NEW hasSGN={r_new['hasSGN']}")
    print()
    print(f"{'링크':<4} {'구분':<5} {'ang.rz(°)':<12} {'STL중심(world mm)':<35} {'→관절piv 거리mm'}")
    print('-'*80)
    for a in ['S','L','U','R','B','T']:
        piv = r_old['joints'].get(a)
        for label, r in [('OLD', r_old), ('NEW', r_new)]:
            rz  = r['angRz'].get(a, '?')
            stl = r['stlBB'].get(a, '?')
            piv = r['joints'].get(a)
            d   = None
            if isinstance(stl,list) and isinstance(piv,list):
                dx,dy,dz = stl[0]-piv[0], stl[1]-piv[1], stl[2]-piv[2]
                d = round((dx**2+dy**2+dz**2)**0.5, 1)
            print(f"  {a:<3} {label:<5} ang.rz={rz:>8}°   stl={str(stl):<35} dist_from_piv={d}")
        print()

asyncio.run(main())
