import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        br = await p.chromium.launch(headless=False)
        pg = await br.new_page()
        await pg.set_viewport_size({'width':1400,'height':900})

        errors = []
        pg.on('pageerror', lambda err: errors.append(f'PAGEERROR: {str(err)[:200]}'))
        pg.on('console', lambda msg: errors.append(f'[{msg.type}] {msg.text[:200]}') if msg.type=='error' else None)

        await pg.goto('http://localhost:8090/DOZIKWORKS_OS_v4_pathcreate.dc.html')
        print('E드라이브 뷰어 로드 중...')
        await pg.wait_for_timeout(14000)

        # favicon 외 에러 필터
        real_errors = [e for e in errors if 'favicon' not in e.lower()]
        print(f'\n콘솔 에러 (favicon 제외): {len(real_errors)}개')
        for e in real_errors:
            print(f'  {e}')

        # 핵심 상태 확인
        result = await pg.evaluate("""() => {
            const app = window.__dzw;
            if (!app) return {error: '__dzw 없음'};
            return {
                TCloaded: typeof window.TransformControls,
                tcAlive: !!(app._tc && typeof app._tc.setMode === 'function'),
                fkOk: typeof app.fk === 'function',
                tcpOffset: app.tcpOffset,
                urdfSigns: (app.urdf||[]).map(u=>({a:u.a,sign:u.sign||1})),
                grpScale: app._grp ? app._grp.scale.x : null
            };
        }""")
        print('\n=== 상태 ===')
        print(f"  TransformControls: {result.get('TCloaded')}")
        print(f"  기즈모(_tc): {result.get('tcAlive')}")
        print(f"  fk 함수: {result.get('fkOk')}")
        print(f"  tcpOffset: {result.get('tcpOffset')}")
        print(f"  urdf signs: {result.get('urdfSigns')}")

        # FK 4점 검증
        fk_result = await pg.evaluate("""async () => {
            const app = window.__dzw;
            const r = await fetch('/weld_path.json');
            const wp = await r.json();
            const arcPoses = wp.poses.filter(p => p.arc === 1);
            const segFlat = wp.segs.flat();
            if (arcPoses.length !== segFlat.length)
                return {error: `길이 불일치: ${arcPoses.length} vs ${segFlat.length}`};
            const n = arcPoses.length;
            const idxs = [0, Math.floor(n/3), Math.floor(n*2/3), n-1];
            return idxs.map(i => {
                const fkr = app.fk(arcPoses[i]);
                const t = segFlat[i];
                const dist = Math.sqrt((fkr.x-t[0])**2+(fkr.y-t[1])**2+(fkr.z-t[2])**2);
                return {idx:i, dist:+dist.toFixed(4), pass:dist<=1.0};
            });
        }""")
        print('\n=== FK 4점 오차 ===')
        expected = [0.0013, 0.0015, 0.0011, 0.0016]
        if isinstance(fk_result, list):
            all_pass = all(r['pass'] for r in fk_result)
            for i, r in enumerate(fk_result):
                match = '✅' if r['pass'] else '❌'
                print(f"  {match} idx={r['idx']} 오차={r['dist']}mm (이전: {expected[i]}mm)")
            print(f"  최종: {'✅ 합격' if all_pass else '❌ 불합격'}")
        else:
            print('  오류:', fk_result)

        # 스크린샷 (기본뷰)
        await pg.screenshot(path='E_drive_verify.png')
        print('\n스크린샷 → E_drive_verify.png')

        await br.close()

asyncio.run(main())
