"""Later reclining-seat support comparison; cushion/body registration unresolved."""
from pathlib import Path
import json
import cadquery as cq
from rear_cabin_layout import layout
OUT=Path(__file__).parent
S=json.loads((OUT.parent/'body-data.json').read_text())['published_reference_dimensions_mm']['wheelbase']/2.4
LAYOUT=layout(json.loads((OUT.parent/'body-data.json').read_text()))
parts=[];holes=[]
def V(p):return cq.Vector(*(v*S for v in p))
def box(w,h,d,p):return cq.Workplane('XY').box(w*S,h*S,d*S).translate(V(p).toTuple()).val()
def cyl(r,l,p,d=(0,1,0)):return cq.Solid.makeCylinder(r*S,l*S,V(p),cq.Vector(*d))
def rod(a,b,r):
 a,b=V(a),V(b);v=b-a;return cq.Solid.makeCylinder(r*S,v.Length,a,v.normalized())
def add(name,shape,color=(.25,.26,.23)):
 assert shape.isValid() and shape.Volume()>0,name
 parts.append((name,shape,color))
for side,label in [(1,'driver'),(-1,'passenger')]:
 cx=side*.38;zc=LAYOUT['seat_center_z_units'];lower=[];upper=[];frame=[];fast=[]
 for rx in [-.15,.15]:
  x=cx+rx
  lo=box(.045,.025,.46,[x,.3625,zc]).cut(box(.035,.025,.464,[x,.3675,zc]))
  up=box(.030,.020,.44,[x,.3685,zc]).cut(box(.022,.020,.444,[x,.3645,zc]))
  for z in [zc-.19,zc+.19]:
   lo=lo.cut(cyl(.004,.04,[x,.345,z]));holes.append([x,.35,z])
   fast.extend([cyl(.0035,.023,[x,.335,z]),cyl(.007,.004,[x,.358,z])])
   frame.append(rod([x,.3785,z],[x,.54,z],.010))
  lower.append(lo);upper.append(up)
  frame.append(rod([x,.54,zc-.21],[x,.54,zc+.21],.012))
 for z in [zc-.21,zc+.21]:frame.append(rod([cx-.15,.54,z],[cx+.15,.54,z],.012))
 for x in [cx-.18,cx+.18]:frame.append(rod([x,.54,zc-.20],[x,1.06,zc-.275],.010))
 frame.append(rod([cx-.18,1.06,zc-.275],[cx+.18,1.06,zc-.275],.010))
 frame.append(box(.36,.014,.025,[cx,.553,zc+.19]))
 add('seat_'+label+'_floor_runner_pair_comparison',cq.Compound.makeCompound(lower))
 add('seat_'+label+'_upper_slide_pair_comparison',cq.Compound.makeCompound(upper))
 add('seat_'+label+'_reclining_frame_comparison',cq.Compound.makeCompound(frame))
 diaphragm=box(.275,.006,.32,[cx,.53,zc])
 # Edge hooks are recognition cues, not a reconstruction of loaded springing.
 hooks=[]
 for x in [cx-.145,cx+.145]:
  for z in [zc-.12,zc-.04,zc+.04,zc+.12]:hooks.append(rod([x,.535,z],[x+(.02 if x<cx else -.02),.53,z],.0025))
 add('seat_'+label+'_diaphragm_comparison',cq.Compound.makeCompound([diaphragm,*hooks]),(.12,.13,.11))
 hinges=[]
 for x in [cx-.18,cx+.18]:hinges.append(cyl(.028,.022,[x-.011,.55,zc-.20],(1,0,0)))
 add('seat_'+label+'_recliner_joint_cues',cq.Compound.makeCompound(hinges),(.40,.41,.36))
 catch_x=cx-side*.15
 catch=cq.Compound.makeCompound([box(.012,.014,.22,[catch_x,.39,zc+.03]),rod([catch_x,.397,zc+.13],[catch_x-side*.07,.397,zc+.20],.005)])
 add('seat_'+label+'_runner_catch_comparison',catch)
 add('seat_'+label+'_floor_fixing_cues',cq.Compound.makeCompound(fast),(.43,.44,.39))
assembly=cq.Assembly(name='unregistered_reclining_seat_support_reference');meshes=[]
for name,shape,color in parts:
 assembly.add(shape,name=name,color=cq.Color(*color));vs,ts=shape.tessellate(.7,.2)
 meshes.append(dict(name=name,color=color,vertices=[round(v,4) for p in vs for v in p.toTuple()],triangles=[i for tri in ts for i in tri]))
assembly.export(str(OUT/'seat-support-reference.step'))
limits='All frame profiles, leg heights, rail sections, positions, catch/hinge shapes, fixing patterns and floor apertures are estimates. Four modeled floor stations per seat are construction geometry, not a reconciled factory fastener count or owner hole map. The former cushion mesh bound Y=.70 was 0.14 body units above reference support plane Y=.56. A declared estimated cushion translation of -.14 replaces that former pose to make the reference assembly coherent; it is not an owner seat-height reading, packing dimension or verified loaded contact. No fitted frame/runner identity, loaded seat/diaphragm behavior, latch engagement, slide/recline travel, restraint strength, fixing torque or verified replacement/removal path. Seatbelt, sensor and headrest-guide variants remain unresolved; no MGB wooden support arrangement is imposed.'
meta=dict(units='mm',factory_sources=['https://www.spridgets.de/downloads/Parts-1977.pdf#page=296','https://www.spridgets.de/downloads/Parts-1977.pdf#page=298','https://www.spridgets.de/downloads/Parts-1977.pdf#page=299'],owner_photos=['IMG_6341','IMG_6329'],basis='Factory GAN6 CHA23/24 reclining-frame, diaphragm and later AHA9946/47 floor-rack / AHA9944/45/43 slide architecture only. Owner photos show tan seat/headrest forms, not hidden frames, runners or floor mounting. Cushion geometry is retained with a declared estimated -.14 body-unit Y translation from its former pose; actual body/seat registration remains unverified.',limits=limits,floor_stations_units=holes,floor_aperture_radius_units=.004,support_plane_units=.56,former_cushion_mesh_lower_bound_units=.70,nominal_former_cushion_underside_units=.72,estimated_cushion_translation_y_units=-.14,current_cushion_mesh_lower_bound_units=.56,cushion_basis='Current roundedBlock center .79 minus half-height .07 minus source bevel .02; mesh bound, not an owner measurement.',former_pose_discrepancy_mm=(.70-.56)*S,parts=meshes)
meta['rear_cabin_placement_revision']=LAYOUT
meta['basis']+=' '+LAYOUT['basis']
meta['limits']+=' '+LAYOUT['limits']
(OUT/'seat-support-reference.json').write_text(json.dumps(meta,separators=(',',':'))+'\n')
restored=cq.importers.importStep(str(OUT/'seat-support-reference.step')).val();assert restored.isValid()
print(json.dumps(dict(groups=len(parts),solids=len(restored.Solids()),step_valid=True,floor_drawing_stations=len(holes),former_pose_discrepancy_mm=meta['former_pose_discrepancy_mm'])))
