import bpy, bmesh, collections
bpy.ops.wm.read_factory_settings(use_empty=True)
bpy.ops.import_scene.gltf(filepath=r'E:/GDRIVE/SERVEUR ET PRODUCTION WEB/2025/REBIRTH/BIG EGG/big-egg-3d/assets/models/enemies/barnacle_brute/barnacle_brute.glb')
me = next(o for o in bpy.context.scene.objects if o.type == 'MESH')
bm = bmesh.new(); bm.from_mesh(me.data)
deform = bm.verts.layers.deform.verify()
def owner(v): return max(v[deform].items(), key=lambda item: item[1])[0]
face_owner = {f: collections.Counter(owner(v) for v in f.verts).most_common(1)[0][0] for f in bm.faces}
print('BEFORE', len(bm.verts), len(bm.faces), sum(e.is_boundary for e in bm.edges), flush=True)
bmesh.ops.remove_doubles(bm, verts=list(bm.verts), dist=0.001)
print('WHOLE_WELDED', len(bm.verts), sum(e.is_boundary for e in bm.edges), sum(not e.is_manifold for e in bm.edges), flush=True)
border = [e for e in bm.edges if len(set(face_owner[f] for f in e.link_faces)) > 1 or len(e.link_faces) > 2]
bmesh.ops.split_edges(bm, edges=border)
for v in bm.verts:
    votes = collections.Counter(face_owner[f] for f in v.link_faces)
    if votes:
        v[deform].clear(); v[deform][votes.most_common(1)[0][0]] = 1.0
boundary = [e for e in bm.edges if e.is_boundary]
print('WELDED', len(bm.verts), len(bm.faces), len(boundary), flush=True)
print('MIXED_FACES', sum(len(set(owner(v) for v in f.verts)) > 1 for f in bm.faces), flush=True)
result = bmesh.ops.holes_fill(bm, edges=boundary, sides=0)
print('FILLED', len(result['faces']), 'REMAINING', sum(e.is_boundary for e in bm.edges), flush=True)
print('CAPS', [(len(f.verts), round(f.calc_area(), 3)) for f in result['faces']][:35], flush=True)
remaining = [e for e in bm.edges if e.is_boundary]
extra = bmesh.ops.edgenet_fill(bm, edges=remaining)
print('NET_FILLED', len(extra['faces']), 'REMAINING', sum(e.is_boundary for e in bm.edges), flush=True)
print('BOUNDARY_DEGREES', collections.Counter(sum(e.is_boundary for e in v.link_edges) for v in bm.verts if any(e.is_boundary for e in v.link_edges)), flush=True)
print('EDGE_FACE_COUNTS', collections.Counter(len(e.link_faces) for e in bm.edges), flush=True)
