import asyncio, json
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        br = await p.chromium.launch(headless=False)

        # ── [1] 정상 상태 ─────────────────────────────────────────────
        pg = await br.new_page()
        await pg.set_viewport_size({'width':1400,'height':900})
        errors = []
        pg.on('pageerror', lambda e: errors.append(f'PAGEERROR: {str(e)[:200]}'))
        pg.on('console', lambda m: errors.append(f'[{m.type}] {m.text[:200]}') if m.type=='error' else None)

        await pg.goto('http://localhost:8090/DOZIKWORKS_OS_v4_pathcreate.dc.html')
        print('[1] 정상 상태 로드 중...')
        await pg.wait_for_timeout(15000)

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

        r1 = await pg.evaluate("""() => {
            const app = window.__dzw;
            if (!app) return {error: '__dzw 없음'};
            return {
                limitMarkers: (app._limitMarkers||[]).length,
                tcAlive: !!(app._tc && typeof app._tc.setMode==='function'),
                fkOk: typeof app.fk==='function',
            };
        }""")
        print(f'\n=== [1] 정상 12500 상태 ===')
        print(f'  빨강 한계마커 수: {r1.get("limitMarkers")} (0이어야 정상)')
        print(f'  기즈모: {r1.get("tcAlive")}')

        # FK 4점
        fk1 = 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();
            const n = arcPoses.length;
            return [0,Math.floor(n/3),Math.floor(n*2/3),n-1].map(i=>{
                const fkr=app.fk(arcPoses[i]); const t=segFlat[i];
                const d=Math.sqrt((fkr.x-t[0])**2+(fkr.y-t[1])**2+(fkr.z-t[2])**2);
                return {idx:i, dist:+d.toFixed(4)};
            });
        }""")
        print('  FK 4점:', fk1)

        await pg.screenshot(path='limit_normal.png')
        print('  스크린샷 → limit_normal.png')
        await pg.close()

        # ── [2] 시험 상태: weld_path.json 한 점 T=-420 으로 intercept ──
        pg2 = await br.new_page()
        await pg2.set_viewport_size({'width':1400,'height':900})
        errors2 = []
        pg2.on('console', lambda m: errors2.append(f'[{m.type}] {m.text[:300]}') if m.type in ('error','warn') else None)

        # weld_path.json 응답을 가로채 poses[77].T = -420 으로 수정 (메모리상만)
        patched = False
        async def intercept(route):
            nonlocal patched
            if 'weld_path.json' in route.request.url and not patched:
                patched = True
                resp = await route.fetch()
                body = await resp.body()
                wp = json.loads(body)
                # poses 중 arc=1인 것의 77번째 점(idx=77)의 T를 -420으로
                arc_count = 0
                for pose in wp['poses']:
                    if pose.get('arc') == 1:
                        if arc_count == 7:  # arc=1 중 8번째 → 전체 poses 내 idx=77에 해당
                            pose['T'] = -420.0
                            break
                        arc_count += 1
                await route.fulfill(body=json.dumps(wp), content_type='application/json',
                                    status=200, headers=dict(resp.headers))
            else:
                await route.continue_()

        await pg2.route('**/*', intercept)
        await pg2.goto('http://localhost:8090/DOZIKWORKS_OS_v4_pathcreate.dc.html')
        print('\n[2] 시험 상태 로드 중 (T=-420 주입)...')
        await pg2.wait_for_timeout(15000)

        limit_warns = [e for e in errors2 if 'LIMIT' in e]
        print('  LIMIT 경고:', limit_warns)

        r2 = await pg2.evaluate("""() => {
            const app = window.__dzw;
            if (!app) return {error: '__dzw 없음'};
            return {
                limitMarkers: (app._limitMarkers||[]).length,
                markerPos: app._limitMarkers && app._limitMarkers[0]
                    ? {x:+app._limitMarkers[0].position.x.toFixed(1), y:+app._limitMarkers[0].position.y.toFixed(1), z:+app._limitMarkers[0].position.z.toFixed(1)}
                    : null,
                tcAlive: !!(app._tc && typeof app._tc.setMode==='function'),
            };
        }""")
        print(f'\n=== [2] 시험 상태 (T=-420 주입) ===')
        print(f'  빨강 한계마커 수: {r2.get("limitMarkers")} (1 이상이어야 정상)')
        print(f'  첫 마커 위치: {r2.get("markerPos")}')
        print(f'  기즈모: {r2.get("tcAlive")}')

        await pg2.screenshot(path='limit_test_red.png')
        print('  스크린샷 → limit_test_red.png')
        await pg2.close()

        # 요약
        print('\n=== 요약 ===')
        n1 = r1.get('limitMarkers', -1)
        n2 = r2.get('limitMarkers', -1)
        print(f'  정상 상태 빨강 마커: {n1}개  {"✅" if n1==0 else "❌"}')
        print(f'  시험 상태 빨강 마커: {n2}개  {"✅" if n2>=1 else "❌"}')
        fk_ok = all(r['dist'] <= 1.0 for r in fk1) if isinstance(fk1, list) else False
        print(f'  FK 4점 합격: {"✅" if fk_ok else "❌"} {[r["dist"] for r in fk1] if isinstance(fk1, list) else fk1}')
        print(f'  콘솔 신규에러: {len(real_errors)}개  {"✅" if len(real_errors)==0 else "❌"}')

        if n1==0 and n2>=1 and fk_ok and len(real_errors)==0:
            print('\n결론: ✅ 빨강 표시 작동 + 무손상')
        else:
            print('\n결론: ❌ 문제 있음 — 위 내용 확인')

        await br.close()

asyncio.run(main())
