# -*- coding: utf-8 -*-
r"""convert_all.py — 상청 STEP 일괄 변환 → fab_models/ 한 곳에 모으기 [CEO 2026-07-19]
F:\설우 의 STEP(.stp/.step)을 웹용 OBJ로 변환. 파일명은 영문(m001..)로(한글 404 방지),
표시이름은 한글 유지해 fab_models/manifest.json 에 목록 기록. 제관 웹이 이 목록으로 부재 선택.
큰 STEP은 거친 tolerance로 속도↑. 이미 있으면 건너뜀(재개 가능).
실행: python convert_all.py
"""
import os, io, json, time, glob, traceback

SRC_ROOT = r'F:\설우'
OUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'fab_models')
MANIFEST = os.path.join(OUT, 'manifest.json')
MAX_MB = 45          # 이보다 큰 STEP은 매우 거칠게(변환시간·메시크기 억제)
LIMIT = 60           # 이번 실행 최대 변환 수

def display_name(path):
    # 폴더 계층에서 의미있는 이름 뽑기: 마지막 2단계 폴더 + 파일명
    p = path.replace('/', '\\').split('\\')
    fn = os.path.splitext(p[-1])[0]
    ctx = p[-3] if len(p) >= 3 else ''
    return (ctx + ' / ' + fn).strip(' /')[:80]

def main():
    os.makedirs(OUT, exist_ok=True)
    man = []
    if os.path.exists(MANIFEST):
        try: man = json.load(io.open(MANIFEST, encoding='utf-8')).get('items', [])
        except Exception: man = []
    done_src = {m['src'] for m in man}
    files = [f for f in glob.glob(os.path.join(SRC_ROOT, '**', '*.st*p'), recursive=True)
             if f.lower().endswith(('.stp', '.step')) and os.path.getsize(f) > 100*1024]
    files.sort(key=lambda f: os.path.getsize(f))   # 작은 것부터(빨리 성과)
    import cadquery as cq
    n = len([m for m in man if m.get('file')])
    made = 0
    for src in files:
        if src in done_src: continue
        if made >= LIMIT: break
        mb = os.path.getsize(src)/1024/1024
        idx = n + made + 1
        outf = 'm%03d.obj' % idx
        outp = os.path.join(OUT, outf)
        try:
            t0 = time.time()
            shp = cq.importers.importStep(src)
            tol = 1.0 if mb > MAX_MB else 0.4
            tmp_stl = outp.replace('.obj', '.stl')
            cq.exporters.export(shp, tmp_stl, tolerance=tol, angularTolerance=0.4)
            import trimesh
            m = trimesh.load(tmp_stl); m.export(outp); os.remove(tmp_stl)
            ext = [round(x,0) for x in m.extents]
            man.append({'name': display_name(src), 'file': 'fab_models/'+outf,
                        'src': src, 'mb': round(os.path.getsize(outp)/1024/1024,1),
                        'size_mm': ext, 'faces': len(m.faces)})
            io.open(MANIFEST, 'w', encoding='utf-8').write(json.dumps({'items': man, 'updated': time.strftime('%Y-%m-%d %H:%M')}, ensure_ascii=False, indent=1))
            made += 1
            print('[%d] %s → %s (%.0f초, 면 %d)' % (idx, display_name(src)[:40], outf, time.time()-t0, len(m.faces)))
        except Exception as e:
            print('[skip] %s: %s' % (os.path.basename(src), str(e)[:80]))
    print('완료 — 이번 변환 %d개, 누적 %d개. manifest: %s' % (made, len(man), MANIFEST))

if __name__ == '__main__':
    main()
