from pathlib import Path
import json,time
import build123d as b
from audit_functional_28 import *
ROOT=Path(__file__).resolve().parents[1]

def rear(n):return (n.startswith('C27_R2_02_') or n.startswith('C27_R2_LTE_') or n=='C27_R2_REF_LTE' or '_HW_LTE_' in n or 'PCB_Rear_Preload' in n or 'Battery_Rear_Pad' in n or 'Battery_Side_Liner' in n or 'Battery_Upper_Liner' in n or 'Battery_Lower_Liner' in n)
def main():
 M,I=load();rows=[]
 for r in M['fasteners']:
  n=r['name'];x,y=r['axis_xy'];bolt=I[n]
  if '_Closure_' in n:
   dia=4.;end=bolt.bb[4]-.0002;start=-40.;chosen=[q for q in I.values() if not q.name.startswith('C27_R2_09_') and q.name!=n and q.kind!='fastener'];stage='closed rigid case, soft rim removed';entry=-12.;floor=-6.2;tip=bolt.bb[5];eng=tip-entry;clear=floor-tip
  elif '_LTE_' in n:
   dia=3.;start=bolt.bb[5]+.0002;end=0.;chosen=[q for q in I.values() if rear(q.name) and q.name!=n and q.kind!='fastener'];stage='rear cover on bench, battery not installed';entry=-20.33;floor=-22.35;tip=bolt.bb[4];eng=entry-tip;clear=tip-floor
  else:
   dia=3.;end=bolt.bb[4]-.0002;start=-35.;chosen=[q for q in I.values() if not rear(q.name) and not q.name.startswith('C27_R2_09_') and q.name not in ('C27_R2_REF_PCB','C27_R2_REF_Battery',n) and q.kind!='fastener'];stage='front subassembly, PCB/battery and rear cover not installed'
   entry,floor=(-10.85,-2.6) if '_Front_Clamp_' in n else (-4.95,-1.1) if '_Speaker_' in n else (-5.1,-2.) if '_Mic_' in n else(-8.3,-5.2)
   tip=bolt.bb[5];eng=tip-entry;clear=floor-tip
  tool=Item('tool',b.Solid.make_cylinder(dia/2,end-start,b.Plane(origin=(x,y,start))),'gauge');hits=[]
  for q in chosen:
   v=overlap(tool,q)
   if v>1e-5:hits.append({'part':q.name,'overlap_mm3':v})
  row={'fastener':n,'standard':r['standard'],'size':r['size'],'length_mm':r['length_mm'],'axis_xy':r['axis_xy'],'tool_shaft_diameter_mm':dia,'tool_approach_z':[start,end],'access_stage':stage,'tool_hits':hits,'measured_tip_z':tip,'nominal_axial_thread_engagement_mm':eng,'tip_to_blind_floor_mm':clear,'thread_note':'Axial engagement of specified major-diameter thread in tapped pilot. Exported standard fastener simplifies helical threads; thread force/strip resistance unqualified.'}
  rows.append(row);print('TOOL',n,len(hits),eng,clear,flush=True)
 (ROOT/'audit/Concept_28_R1_fastener_access.json').write_text(json.dumps(rows,indent=2))
 g=Item('USB_GAUGE',b.import_step(ROOT/'inputs/final27/cad/Concept_27_R2_USB_C_GAUGE.step'),'gauge');u=[]
 shells=[q for q in I.values() if q.kind!='electronics' and q.kind!='fastener']
 # Stop at reference full seating, sample approach from 15mm outboard.
 for d in [15,10,5,2,1,.5,0]:
  gg=g.moved([-d,0,0]);hits=[]
  for q in shells:
   v=overlap(gg,q)
   if v>1e-5:hits.append({'part':q.name,'overlap_mm3':v})
  u.append({'remaining_insertion_mm':d,'case_part_hits':hits});print('USB',d,len(hits),flush=True)
 # The plug is a mechanical thin-shell gauge, not a vendor-qualified connector.
 pcb=I['C27_R2_REF_PCB'];full=overlap(g,pcb,True)
 (ROOT/'audit/Concept_28_R1_USB_insertion.json').write_text(json.dumps({'gauge':'8.31x2.46 shell; 12.85x7 housing; 6.65mm gauge length; no vendor plug CAD supplied','axis':'+X','samples':u,'fully_seated_gauge_vs_actual_PCB_solids':full,'electrical_mating_qualified':False},indent=2))
 frames=[q for q in I.values() if q.name in ('C27_R2_LTE_Lower_Service_Frame','C27_R2_LTE_Upper_Service_Frame')];back=next(q for q in I.values() if q.name.startswith('C27_R2_02_'));paths={}
 for frame in frames:
  path=[]
  for z in [0,.5,1,2,4,8,12,16]:path.append({'lift_mm':z,'overlap_with_back_mm3':overlap(frame.moved([0,0,z]),back)})
  paths[frame.name]=path
 (ROOT/'audit/Concept_28_R1_LTE_service_path.json').write_text(json.dumps(paths,indent=2));print('LTE_PATH',paths,flush=True)
if __name__=='__main__':main()
