from pathlib import Path
import sys,re,json,uuid,shutil
R=Path(__file__).resolve().parent;B=R.parent;sys.path.insert(0,str(B/'parity_metadata_closure_A22'));from prepare_candidates import forms,run,sha
D=R/'IR_schematic_candidate';D.mkdir(exist_ok=True);N='lamp_safety_evt_a2_IR_interface';S=R/'paired/lamp_safety_evt_a1_metadata.kicad_sch';s=S.read_text();s=s.replace('(paper "A3")','(paper "A2")');s=s.replace('(project "lamp_safety_evt_a1_metadata"','(project "'+N+'"')
u=lambda:str(uuid.uuid4());root=re.search(r'\(uuid "([^"]+)"',s).group(1)
lib=list(forms(s,'lib_symbols'))[0];defs=list(forms(lib[2],'symbol'));conn=next(f for _,_,f in defs if f.startswith('(symbol "Project:CONN4"'))
for st,en,f in reversed(list(forms(conn,'pin'))):
 if '(number "4"' in f:conn=conn[:st]+conn[en:]
conn=conn.replace('CONN4','CONN3');s=s[:lib[1]-1]+conn+s[lib[1]-1:]
# Remove only the known MCU PC15 NC marker.
removed=0
for st,en,f in reversed(list(forms(s,'no_connect'))):
 if '(at 189.23 111.76)' in f:s=s[:st]+s[en:];removed+=1
assert removed==1
add=[]
def label_net(x,y,name):
 add.append(f'(wire (pts (xy {x:.2f} {y:.2f}) (xy {x+7.62:.2f} {y:.2f})) (stroke (width 0) (type default)) (uuid "{u()}"))')
 add.append(f'(label "{name}" (at {x+7.62:.2f} {y:.2f} 0) (effects (font (size 1 1)) (justify left bottom)) (uuid "{u()}"))')
def symbol(ref,value,libid,footprint,x,y):
 add.append(f'(symbol (lib_id "Project:{libid}") (at {x:.2f} {y:.2f} 0) (unit 1) (in_bom yes) (on_board yes) (dnp no) (uuid "{u()}") (property "Reference" "{ref}" (at {x:.2f} {y-13:.2f} 0) (effects (font (size 1 1)))) (property "Value" "{value}" (at {x:.2f} {y-10.46:.2f} 0) (effects (font (size 1 1)))) (property "Footprint" "{footprint}" (at {x:.2f} {y:.2f} 0) (effects (font (size 1 1)) (hide yes))) (property "Datasheet" "" (at {x:.2f} {y:.2f} 0) (effects (font (size 1 1)) (hide yes))) (instances (project "{N}" (path "/{root}" (reference "{ref}") (unit 1)))))')
symbol('J6','IR SENSOR 3V3 ACTIVE HIGH','CONN3','Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical',200.66,340.36)
for y,n in [(335.28,'CTRL_3V3'),(340.36,'GND'),(345.44,'IR_SENSOR')]:label_net(195.58,y,n)
for ref,value,libid,x in [('R20','1k 1%','RES',100.33),('R21','47k 1%','RES',130.81),('C8','10n X7R 16V','CAP',161.29)]:
 fp=('Capacitor_SMD:C_' if libid=='CAP' else 'Resistor_SMD:R_')+'0603_1608Metric'
 symbol(ref,value,libid,fp,x,340.36)
 label_net(x,335.28,'IR_SENSOR' if ref=='R20' else 'IR_HAND')
 label_net(x,345.44,'IR_HAND' if ref=='R20' else 'GND')
add.append(f'(wire (pts (xy 189.23 111.76) (xy 181.61 111.76)) (stroke (width 0) (type default)) (uuid "{u()}"))')
add.append(f'(label "IR_HAND" (at 181.61 111.76 180) (effects (font (size 1 1)) (justify right bottom)) (uuid "{u()}"))')
s=s.replace('PA9 heartbeat, PA10 thermal status.','PA11 heartbeat, PA12 thermal status default mapping; PC15 IR candidate input.')
add.append(f'(text "IR candidate: J6 1=CTRL_3V3,2=GND,3=active-high 3V3 push-pull presence. No 5V input. R20=1k, R21=47k to GND, C8=10n. Sensor optical design and RTC/PC15 binding pending; NOT FOR FABRICATION." (at 25 285 0) (effects (font (size 1 1)) (justify left)) (uuid "{u()}"))')
s=s.rstrip()[:-1]+''.join(add)+')\n';p=D/(N+'.kicad_sch');p.write_text(s)
shutil.copy2(R/'paired/lamp_safety_evt_a1_metadata.kicad_pro',D/(N+'.kicad_pro'))
lib=list(forms(s,'lib_symbols'))[0][2];lib=re.sub(r'^\(\s*lib_symbols\s+','',lib)[:-1];lib=re.sub(r'(\(symbol\s+")Project:',r'\1',lib)
(D/'Project.kicad_sym').write_text('(kicad_symbol_lib (version 20241209) (generator "kicad_symbol_editor")\n'+lib+'\n)\n');shutil.copy2(R/'paired/sym-lib-table',D/'sym-lib-table')
run(['sch','erc','--severity-all','--format','json','--output',str(D/'erc.json'),str(p)],D/'erc.log')
run(['sch','export','netlist','--format','kicadxml','--output',str(D/'netlist.xml'),str(p)],D/'netlist.log')
run(['sch','export','svg','--output',str(D/'preview'),str(p)],D/'preview.log')
j=json.loads((D/'erc.json').read_text());v=[x for sh in j['sheets'] for x in sh.get('violations',[])];print('IR candidate ERC findings:',len(v));print(v[:2]);assert not v,v
