import asyncio, math
from playwright.async_api import async_playwright

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

JS_INFO = """
()=>{
    var app=window.__dzw; var T=app&&app._T;
    if(!app||!T) return {err:'no app'};
    app._grp&&app._grp.updateMatrixWorld(true);
    var jArr=app.state&&app.state.joints;
    var jv=Array.isArray(jArr)&&Array.isArray(jArr[1])?jArr[1]:null;
    var src=(app.poseRobot||'').toString();
    // ang 회전값
    var rz={};
    ['S','L','U','R','B','T'].forEach(function(a){
        var ag=app.gj&&app.gj[a]; if(ag) rz[a]=+(ag.rotation.z*180/Math.PI).toFixed(2);
    });
    // STL BB of U link (핵심)
    var uBB=null;
    if(app.gj&&app.gj.U){
        var box=new T.Box3();
        app.gj.U.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);
            }
        });
        if(!box.isEmpty()){var cen=new T.Vector3(); box.getCenter(cen);
            uBB=[+(cen.x*1000).toFixed(1),+(cen.y*1000).toFixed(1),+(cen.z*1000).toFixed(1)];}
    }
    return {hasSGN:src.includes('SGN'), joints:jv, angRz:rz, uLinkBB:uBB};
}
"""

async def check(br, url, label, shot):
    pg = await br.new_page()
    await pg.set_viewport_size({'width':1536,'height':1024})
    await pg.goto(url)
    await pg.wait_for_timeout(22000)
    info = await pg.evaluate(JS_INFO)
    await pg.evaluate(JS_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)
    await pg.close()
    return info

async def main():
    BASE = 'http://localhost:8090'
    async with async_playwright() as p:
        br = await p.chromium.launch(headless=True)
        print('27831c2 원본 측정...')
        old = await check(br, f'{BASE}/old_check.html',   'OLD', 'cmp_old.png')
        print('현재 파일 측정...')
        new = await check(br, f'{BASE}/DOZIKWORKS_OS_v4_pathcreate.dc.html', 'NEW', 'cmp_new.png')
        await br.close()

    print('\n=== 비교 ===')
    print(f'           OLD (27831c2)          현재')
    print(f'hasSGN:    {old["hasSGN"]}              {new["hasSGN"]}')
    print(f'joints:    {old["joints"]}')
    print(f'           {new["joints"]}')
    for a in ['S','L','U','R','B','T']:
        ov = old['angRz'].get(a,'?')
        nv = new['angRz'].get(a,'?')
        match = '✅' if isinstance(ov,float) and isinstance(nv,float) and abs(ov-nv)<0.1 else '❌'
        print(f'ang.{a}.rz: {ov:>9}°  vs  {nv:>9}°  {match}')
    print(f'U STL BB:  {old["uLinkBB"]}')
    print(f'           {new["uLinkBB"]}')
    diff = None
    if old['uLinkBB'] and new['uLinkBB']:
        diff = round(sum((a-b)**2 for a,b in zip(old['uLinkBB'],new['uLinkBB']))**0.5, 1)
    print(f'U STL 차이: {diff}mm  {"✅ 일치" if diff is not None and diff<10 else "❌ 다름"}')

asyncio.run(main())
