"""Read-only native Fusion audit for the generated RS06 r01 document."""
from pathlib import Path
import hashlib
import json
import adsk.core as ac
import adsk.fusion as af

HERE = Path(__file__).resolve().parent


def run(_context):
    d = af.Design.cast(ac.Application.get().activeProduct)
    assert d.parentDocument.name == 'Shappy V2 - RS06 Whole Robot r01'
    p = json.loads((HERE / 'parameters.json').read_text())
    analysis = json.loads((HERE / 'analysis.json').read_text())
    checks = json.loads((HERE / 'cad/cad_checks.json').read_text())
    for filename, key in [('fusion_build.py', 'source_sha256'), ('parameters.json', 'parameters_sha256')]:
        assert hashlib.sha256((HERE / filename).read_bytes()).hexdigest() == checks[key]
    assert analysis['source_sha256']['parameters.json'] == checks['parameters_sha256']
    healthy = all(i.healthState == af.FeatureHealthStates.HealthyFeatureHealthState for i in d.timeline)
    assert healthy
    expected = analysis['poses']['stand']['foot_centers_mm']
    feet, housings, bodies, uppers = {}, 0, 0, 0
    for o in d.rootComponent.occurrences:
        if o.component.name == 'PETG_upper_link_200':
            assert o.component.bRepBodies.count == 1
            uppers += 1
        for b in o.component.bRepBodies:
            assert b.isSolid
            bodies += 1
            housings += b.name == 'RS06_D90_L55_reference_housing'
            if o.component.name == 'D40_foot_ball_REFERENCE':
                c = b.physicalProperties.centerOfMass
                c.transformBy(o.transform2)
                xyz = [getattr(c, a) * 10 for a in 'xyz']
                leg = ('F' if xyz[0] > 0 else 'R') + ('L' if xyz[1] > 0 else 'R')
                feet[leg] = xyz
    assert housings == p['motor']['count'] == 12
    assert uppers == 4 and bodies == checks['body_count'] == 175
    assert set(feet) == set(expected)
    error = max(abs(feet[l][i] - expected[l][i]) for l in feet for i in range(3))
    assert error < 1e-6
    # Eight intentional overlaps: four belts and two tooth-envelope pulleys each.
    collisions = checks['standing_interferences']
    assert len(collisions) == 8
    assert all('600S5M250_belt_PITCH_PATH_not_teeth' in c['two'] and
               c['one'].startswith('S5M_belt_drive_40T_600_25 / ') for c in collisions)
    masses = {}
    for kind, density in [('aluminum', 2.70), ('PETG', 1.27), ('steel', 7.85)]:
        volume = sum(b['volume_mm3'] for b in checks['body_records'] if b['kind'] == kind)
        masses[kind] = {'volume_mm3': volume, 'assumed_density_g_cm3': density,
                        'mass_kg': volume * density / 1e6}
    motor_mass = housings * p['motor']['catalog_mass_g'] / 1000
    subtotal = motor_mass + sum(m['mass_kg'] for m in masses.values())
    report = {
        'checked_on': '2026-10-28', 'revision': p['revision'],
        'scope': 'current nominal pose native solids, placement, source identity and partial mass arithmetic',
        'result': 'pass within stated scope', 'native_bodies': bodies,
        'motor_housings': housings, 'connected_upper_links': uppers,
        'timeline_healthy': healthy, 'foot_centers_mm': feet,
        'max_foot_center_difference_from_kinematics_mm': error,
        'unexpected_positive_volume_interferences': 0,
        'intentional_belt_tooth_envelope_interferences': len(collisions),
        'mass_estimate': {'motor_catalog_mass_kg': motor_mass, 'modeled_materials': masses,
                          'partial_subtotal_kg': subtotal,
                          'excluded': ['pulleys and belts', 'bearings', 'foot elastomer',
                                       'battery and electronics', 'wiring', 'unmodeled fasteners'],
                          'basis': 'solid CAD volumes at assumed densities; not a measured mass or complete BOM'},
        'not_verified': ['joint motion clearance', 'strength and stiffness', 'belt preload and capacity',
                         'fastener fits and torque transmission', 'thermal duty', 'physical operation'],
        'source_sha256': {n: hashlib.sha256((HERE / n).read_bytes()).hexdigest()
                          for n in ['verify_cad.py', 'fusion_build.py', 'parameters.json', 'analysis.json',
                                    'cad/cad_checks.json', 'cad/shappy_rs06_r01.step',
                                    'cad/shappy_rs06_r01.f3d', 'viewer/scene.json']},
    }
    (HERE / 'cad/verification.json').write_text(json.dumps(report, indent=2) + '\n')
    print(json.dumps({k: report[k] for k in ['result', 'native_bodies', 'motor_housings',
                                            'max_foot_center_difference_from_kinematics_mm']}))
    print('Partial solid-model mass subtotal kg:', subtotal)
