import asyncio, math
from playwright.async_api import async_playwright

CAMERAS = [
    ('FRONT', -math.pi/2,  math.pi/2*0.6, 3.5),
    ('RIGHT',  0.0,         math.pi/2*0.6, 3.5),
    ('LEFT',   math.pi,     math.pi/2*0.6, 3.5),
    ('TOP',   -math.pi/2,   0.15,          4.0),
]
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_CHECK = """
() => {
    var app = window.__dzw;
    var T = app && app._T;
    if(!app || !T) return {err:'no app'};
    app._grp && app._grp.updateMatrixWorld(true);

    // SGN 여부
    var src = (app.poseRobot||'').toString();
    var hasSGN = src.includes('SGN');

    // 홈자세 확인
    var jArr = app.state && app.state.joints;
    var jVals = Array.isArray(jArr) && Array.isArray(jArr[1]) ? jArr[1] : null;

    // ang 회전값
    var angRz = {};
    ['S','L','U','R','B','T'].forEach(function(a){
        var ag = app.gj && app.gj[a];
        if(ag) angRz[a] = +(ag.rotation.z * 180/Math.PI).toFixed(2);
    });

    // U STL BB (연결 여부 판단)
    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)];
        }
    }

    // FK 4점 (arc 구간)
    var csvPoses = app._csvPoses || [];
    var arc = csvPoses.filter(function(p){ return p.arc === 1; });
    var seg = [].concat.apply([], app._weldSegs || []);
    var n = arc.length; var fkMax = 0; var fkDetails = [];
    [0, Math.floor(n/3), Math.floor(n*2/3), n-1].forEach(function(i){
        if(i < 0 || i >= n) return;
        var fk = app.fk(arc[i]);
        var t = seg[i] || [0,0,0];
        var d = Math.sqrt((fk.x-t[0])*(fk.x-t[0])+(fk.y-t[1])*(fk.y-t[1])+(fk.z-t[2])*(fk.z-t[2]));
        fkDetails.push({i:i, d:+d.toFixed(4), fk:[+fk.x.toFixed(2),+fk.y.toFixed(2),+fk.z.toFixed(2)], t:[+t[0].toFixed(2),+t[1].toFixed(2),+t[2].toFixed(2)]});
        if(d > fkMax) fkMax = d;
    });

    // 콘솔 에러는 Playwright 레벨에서 수집
    var mc = 0;
    if(app._robotGrp) app._robotGrp.traverse(function(o){if(o.isMesh)mc++;});

    return {hasSGN, jVals, angRz, uBB, fkMax: +fkMax.toFixed(4), fkDetails, meshCount: mc};
}
"""

async def main():
    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})
        errors = []
        pg.on('console', lambda m: errors.append(m.text) if m.type=='error' else None)
        pg.on('pageerror', lambda e: errors.append(str(e)))
        await pg.goto('http://localhost:8090/DOZIKWORKS_OS_v4_pathcreate.dc.html')
        await pg.wait_for_timeout(22000)

        r = await pg.evaluate(JS_CHECK)
        if 'err' in r:
            print('ERROR:', r); await br.close(); return

        print('=== v5방식 이식 검증 ===')
        print(f'SGN 없음:     {"✅" if not r["hasSGN"] else "❌ SGN 있음!"}')
        print(f'joints:       {r["jVals"]}')
        home = [-0.12,-63.80,-36.73,0.01,-90.97,-5.53]
        is_home = r['jVals'] and all(abs(r['jVals'][i]-home[i])<0.1 for i in range(6))
        print(f'홈자세 일치:  {"✅" if is_home else "⚠️  (JBI 로드 후 자세)"}')
        print(f'ang.U.rz:     {r["angRz"].get("U","?")}° (홈자세=-36.73° 기대)')
        print(f'U STL 중심:   {r["uBB"]}')
        print(f'로봇 메시:    {r["meshCount"]}개')
        print(f'콘솔 에러:    {len(errors)}건  {"✅" if not errors else "❌"}')
        if errors: print('  에러:', errors[:3])
        print()
        print(f'FK 최대오차:  {r["fkMax"]}mm  {"✅ 1mm 이내" if r["fkMax"]<1.0 else "❌ 1mm 초과"}')
        for d in r['fkDetails']:
            print(f'  점[{d["i"]:3d}]: FK={d["fk"]}  csv={d["t"]}  Δ={d["d"]}mm')

        print('\n4방향 스크린샷...')
        for (name,theta,phi,rv) in CAMERAS:
            await pg.evaluate(JS_CAM, {'theta':theta,'phi':phi,'r':rv})
            await pg.wait_for_timeout(350)
            fn = f'v5method_{name.lower()}.png'
            await pg.screenshot(path=fn)
            print(f'  {name} → {fn}')

        await br.close()

asyncio.run(main())
