"""Independent measurements of native geometry, edit isolation, camera, and GLB import."""
import bpy, json, hashlib, sys
from pathlib import Path
from mathutils import Vector
ROOT=Path(__file__).resolve().parents[1]
BASELINE=Path(sys.argv[sys.argv.index('--')+1]).resolve()

def bounds(objects):
    pts=[o.matrix_world@Vector(v) for o in objects for v in o.bound_box]
    return [round(max(v[i] for v in pts)-min(v[i] for v in pts),6) for i in range(3)]

def snapshot(path):
    bpy.ops.wm.open_mainfile(filepath=str(path));bpy.context.view_layer.update()
    s=bpy.context.scene
    meshes=[o for o in s.objects if o.type=='MESH' and o.name!='Studio_Ground']
    result={'mesh_count':len(meshes),'wheel_count':sum(o.name.startswith('Wheel_') for o in meshes),
        'tagged_editable_count_legacy':sum(bool(o.get('editable_part')) for o in s.objects),
        'camera_location':list(s.camera.location),'unit_system':s.unit_settings.system,
        'body_envelope_m':bounds([o for o in meshes if o.name.startswith('Body_') or o.name=='Front_Bumper']),
        'tyre_outer_width_m':bounds([o for o in meshes if o.name.startswith('Wheel_')])[1],
        'ground_tagged_editable':bool(bpy.data.objects['Studio_Ground'].get('editable_part')),
        'model_identifier':s.get('model_identifier'), 'edit_source_sha256':s.get('edit_source_sha256'),
        'parts':{}}
    for o in meshes:
        m=o.data.materials[0]
        result['parts'][o.name]={'dimensions': [round(v,6) for v in o.dimensions],
            'location':[round(v,6) for v in o.location],
            'mesh_sha256':hashlib.sha256(repr([(tuple(v.co)) for v in o.data.vertices]).encode()).hexdigest(),
            'material':m.name,'color':[round(v,6) for v in m.diffuse_color]}
    return result

r={'baseline':{},'astra':{},'checks':[]}
for variant in ('base','edited'):
    r['baseline'][variant]=snapshot(BASELINE/f'fieldnote_r1_{variant}.blend')
    r['astra'][variant]=snapshot(ROOT/f'fieldnote_r1_{variant}.blend')

def check(name,value):r['checks'].append({'name':name,'pass':bool(value)})
a=r['astra']['base'];b=r['astra']['edited']
for part,axis,delta in [('Mast_Column',2,.30),('Mast_Head',0,.12),('Sample_Pod',0,.20)]:
    actual=b['parts'][part]['dimensions'][axis]-a['parts'][part]['dimensions'][axis]
    check(part+' dimension delta',abs(actual-delta)<1e-5)
check('mast head raised 0.30m',abs(b['parts']['Mast_Head']['location'][2]-a['parts']['Mast_Head']['location'][2]-.30)<1e-5)
allowed={'Mast_Column','Mast_Head','Mast_Lens','Sample_Pod','Sample_Pod_Cap','Roof_Panel'}|{f'Roof_Cell_{i:02}' for i in range(1,5)}
changed=[name for name in a['parts'] if a['parts'][name]!=b['parts'][name]]
r['astra_changed_parts']=changed
check('only requested parts and attachments changed',set(changed)<=allowed)
check('object names preserved',set(a['parts'])==set(b['parts']))
for name in ('Mast_Head','Sample_Pod'):
    check(name+' accessory material preserved',a['parts'][name]['color']==b['parts'][name]['color'])
check('roof color changed',a['parts']['Roof_Panel']['color']!=b['parts']['Roof_Panel']['color'])
check('edit actually started from base file',b['edit_source_sha256']==hashlib.sha256((ROOT/'fieldnote_r1_base.blend').read_bytes()).hexdigest())
for name,snap in r['astra'].items():
    check(name+' four independent wheels',snap['wheel_count']==4)
    check(name+' >=20 genuine mesh parts',snap['mesh_count']>=20)
    check(name+' metric units',snap['unit_system']=='METRIC')
    check(name+' saved camera positioned',sum(abs(x) for x in snap['camera_location'])>1)
    check(name+' body length 1.60m',abs(snap['body_envelope_m'][0]-1.6)<1e-5)
    check(name+' body width 1.05m',abs(snap['body_envelope_m'][1]-1.05)<1e-5)
    check(name+' tyres width 1.40m',abs(snap['tyre_outer_width_m']-1.4)<1e-5)
    check(name+' Astra identifier stored',snap['model_identifier']=='gpt-6-astra')

r['glb']={}
for variant in ('base','edited'):
    bpy.ops.wm.read_factory_settings(use_empty=True)
    bpy.ops.import_scene.gltf(filepath=str(ROOT/f'fieldnote_r1_{variant}.glb'))
    meshes=[o for o in bpy.context.scene.objects if o.type=='MESH']
    names={o.name for o in meshes}
    r['glb'][variant]={'meshes':len(meshes),'names':sorted(names)}
    check(variant+' GLB preserves all part names',names==set(a['parts']))
r['all_pass']=all(c['pass'] for c in r['checks'])
(ROOT/'evidence/comparison.json').write_text(json.dumps(r,indent=2)+'\n')
print(json.dumps({'all_pass':r['all_pass'],'checks':r['checks'],
    'baseline_body':r['baseline']['base']['body_envelope_m'],
    'baseline_tyre_width':r['baseline']['base']['tyre_outer_width_m'],
    'astra_meshes':a['mesh_count'],'changed':changed},indent=2))
assert r['all_pass'],'Verification failed; see comparison.json'
