"""분리 검증: 구조(계층)·독립이동(플랜지↔몸통)·콘솔에러 + 파트별 색 렌더 캡처."""
import asyncio, json
from playwright.async_api import async_playwright
URL='http://localhost:8090/DOZIKWORKS_OS_v5_locked.dc.html'
OUT=r'E:\도진팩토리\3D스캔및티칭시스템\shots\ceo_feedback'

async def main():
    async with async_playwright() as p:
        br=await p.chromium.launch(channel='msedge',headless=True)
        pg=await br.new_page(viewport={'width':1400,'height':1000})
        errs=[]; pg.on('console',lambda m: errs.append(m.text) if m.type=='error' else None)
        pg.on('pageerror',lambda e: errs.append('PAGEERR:'+str(e)))
        await pg.goto(URL)
        await pg.wait_for_function("window.__dzw && window.__dzw._torchParts", timeout=15000)
        res=await pg.evaluate("""()=>{ const d=window.__dzw, T=d._T; const out={};
          const f=d._torchFlange, b=d._torchBody;
          out.names=[f.name,b.name];
          out.body_parent_is_flange = (b.parent===f);
          out.flange_parent_is_torchNode = (f.parent===d._torchNode);
          // 삼각형 수
          out.flange_tris = f.geometry.attributes.position.count/3;
          out.body_tris = b.geometry.attributes.position.count/3;
          // 독립이동 1: 플랜지를 로컬 +Z 50mm 이동 → 몸통 월드도 ~50 따라오는지
          d._torchNode.updateMatrixWorld(true);
          const bw0=new T.Vector3(); b.getWorldPosition(bw0);
          const fw0=new T.Vector3(); f.getWorldPosition(fw0);
          f.position.z+=50; f.updateMatrixWorld(true); b.updateMatrixWorld(true);
          const bw1=new T.Vector3(); b.getWorldPosition(bw1);
          out.flangeMove_bodyFollow_mm = +bw0.distanceTo(bw1).toFixed(1);   // 기대 ~50 (scene스케일 아님, 로컬mm)
          f.position.z-=50; f.updateMatrixWorld(true); b.updateMatrixWorld(true);
          // 독립이동 2: 몸통만 로컬 +Z 50 → 플랜지 월드 불변
          const fw_before=new T.Vector3(); f.getWorldPosition(fw_before);
          b.position.z+=50; b.updateMatrixWorld(true);
          const fw_after=new T.Vector3(); f.getWorldPosition(fw_after);
          out.bodyMove_flangeStays_mm = +fw_before.distanceTo(fw_after).toFixed(3);  // 기대 0
          b.position.z-=50; b.updateMatrixWorld(true);
          // 이동은 로컬좌표 기준이라 값 자체가 mm. 따라오는 거리는 로컬델타=50를 부모행렬로 → 스케일 반영됨.
          return out;
        }""")
        print("=== 분리 구조/이동 검증 ===")
        print(json.dumps(res,ensure_ascii=False,indent=1))
        print("=== 콘솔 에러 ===", errs if errs else "없음")
        # 파트별 색 렌더: 플랜지=빨강, 몸통=회색 → 분리 경계 시각 확인
        await pg.evaluate("""()=>{ const d=window.__dzw, T=d._T; const f=d._torchFlange, b=d._torchBody;
          f.material=new T.MeshLambertMaterial({color:0xff2a18}); b.material=new T.MeshLambertMaterial({color:0x9099a5});
          f.updateMatrixWorld(true); const box=new T.Box3().setFromObject(f.parent);
          const c=new T.Vector3(); box.getCenter(c); const sph=box.getBoundingSphere(new T.Sphere());
          if(d.orbit){ d.orbit.tgt.copy(c); d.orbit.r=sph.radius*2.4; d.orbit.theta=-0.6; d.orbit.phi=1.45; d.updateCam&&d.updateCam(); }
        }""")
        await pg.wait_for_timeout(400)
        await pg.screenshot(path=OUT+r'\SPLIT_result_parts.png')
        await br.close()

asyncio.run(main())
