"""Apply the UC1 release approach to final R2's actual boss geometry in Fusion.
Run immediately after 01, before the cosmetic edits in 03. Does not execute Adam source.
"""
import adsk.core,adsk.fusion,pathlib,json,math,traceback
OUT=pathlib.Path(C28_ROOT)
app=adsk.core.Application.get();d=adsk.fusion.Design.cast(app.activeProduct);root=d.rootComponent
tm=adsk.fusion.TemporaryBRepManager.get();BT=adsk.fusion.BooleanTypes;P=adsk.core.Point3D

def cylinder(x,y,r,z0,z1,r1=None):return tm.createCylinderOrCone(P.create(x/10,y/10,z0/10),r/10,P.create(x/10,y/10,z1/10),(r if r1 is None else r1)/10)
def operation(a,b,op):
 assert tm.booleanOperation(a,b,op)
 return a
def change(o,b):
 inv=o.transform2.copy();inv.invert();tm.transform(b,inv);f=o.component.features.baseFeatures.item(0)
 f.startEdit()
 try:assert f.updateBody(f.sourceBodies[0],b)
 finally:f.finishEdit()
 d.timeline.moveToEnd()
def bounds(b):
 q=b.boundingBox;return [10*v for v in [q.minPoint.x,q.maxPoint.x,q.minPoint.y,q.maxPoint.y,q.minPoint.z,q.maxPoint.z]]
try:
 rows=[]
 for num in [1,2]:
  o=next(o for o in root.allOccurrences if o.component.name.startswith(f'C27_R2_{num:02d}_'))
  body=tm.copy(o.bRepBodies.item(0));before=body.volume*1000
  sites=[]
  for x in [-33.4,33.4]:
   for y in [-56,56]:sites.append((x,y,2.8,-12,-10,'low')if num==1 else(x,y,2.8,-14,-12,'high'))
  for x in ([-9.1,9.1]if num==1 else[-14,14]):
   for y in ([18.0,66.0]if num==1 else[-32,64]):sites.append((x,y,2.55,-4.95,-2.1,'low')if num==1 else(x,y,2.7,-21.81,-20.33,'high'))
  for x,y,r,z0,z1,tip in sites:
   rr=r+.1*math.tan(math.radians(1));rt=rr-(z1-z0)*math.tan(math.radians(1))
   a,b=(rt,rr)if tip=='low'else(rr,rt)
   wedge=operation(cylinder(x,y,r,z0,z1),cylinder(x,y,a,z0,z1,b),BT.DifferenceBooleanType)
   v=body.volume*1000;body=operation(body,wedge,BT.DifferenceBooleanType)
   rows.append({'part':o.component.name,'centerXY':[x,y],'zRange':[z0,z1],'draftDegrees':1,'rootLandMm':.1,'removedMm3':v-body.volume*1000,'tipRadiusMm':rt,'tipEnd':tip})
  change(o,body)
 (OUT/'audit/final27_casting_adaptation.json').write_text(json.dumps({'baseline':'Final Adam R2 imported into Fusion; no Adam execution','bossTapers':rows,'localReleaseOnly':True,'LTE_boss_tip_adapted_to_final_R2_mm':-20.33},indent=2))
 inventory=[]
 for c in d.allComponents:
  inventory.append({'name':c.name,'bodies':[{'name':b.name,'volume_mm3':b.volume*1000,'bbox_mm':bounds(b),'faces':b.faces.count}for b in c.bRepBodies]})
 (OUT/'audit/fusion_import_inventory.json').write_text(json.dumps({'baseline':'final 27 R2 with native UC1-style tapers','components':inventory},indent=2))
 ex=d.exportManager;hidden=[]
 for o in root.allOccurrences:
  if '_REF_'in o.component.name:hidden.append(o);o.isLightBulbOn=False
 step=ex.createSTEPExportOptions(str(OUT/'cad/Concept_28_R1_Functional_Baseline_CASE.step'));step.isIncludingInvisibleComponents=False;step.isIncludingInvisibleBodies=False;assert ex.execute(step)
 for o in hidden:o.isLightBulbOn=True
 assert ex.execute(ex.createFusionArchiveExportOptions(str(OUT/'cad/Concept_28_R1_Imported_27_Baseline.f3d')))
 print('16 native boss-release tapers applied to final R2; baseline and inventory saved.')
except:
 (OUT/'audit/casting_adaptation_error.txt').write_text(traceback.format_exc());print(traceback.format_exc())
